注1:使用decltype()的时候,左值和右值不同。表达式的结果是左值,使用decltype后得到引用类型,如解引用运算符。当表达式的结果是右值时,如取地址运算符(作用于左值a,表达式结果&a为右值,一个指向该运算对象的指针)
int *p=&a;//解引用运算符生成左值。
decltype(*p);//该表达式的结果是 int&;
decltype(&p);//该表达式的结果是int **,指向整形指针的指针。
decltype(&a);//该表达式的结果是int *,指向a的指针
注2:
1)赋值运算符 = 需要一个左值(非常量的)作为该运算符的左侧运算对象,得到的结果也是一个左值。
2)取地址符:作用于左值运算对象,返回一个指向该运算对象的指针,该指针是一个右值。
3)内置解引用运算符、下标运算符 等求值结果都是左值,
4)内置类型和迭代器的递增递减运算符作用于左值,前置时结果也是左值。
2.2.1 优先级与结合律:
优先级相同,按从左到右的顺序
括号
优先级表:同一组内的运算符优先级相等,组的位置越靠前优先级越高
2.2.2 运算对象的求值顺序:
大多数情况下,不会明确指明求值顺序。
表达式指向并修改了同一对象,会发生错误,如:
cout<<i<<" "<<++i<<endl;
4种明确规定了运算对象的顺序的运算符:逻辑与(&&)、逻辑或(||)、条件(?:)、逗号运算符(,)。
注:1)参与取余运算的运算对象必须是整数。
2)int/int 结果还是int。舍弃小数部分,
3)m%n,结果的符号与m相同。
运算对象与求值结果都是右值。
逻辑与和逻辑或:短路求值
关系运算符都满足:左结合律
注意关系运算符不能连用。
int i =0;//初始化,非赋值
const int ci = i;//初始化,非赋值
1024 = i;//错,字面值是右值
i+j = k;//算术表达式是右值
ci = k;//ci是常量
如果赋值运算符的左侧运算对象是 内置类型(整型数、浮点数、字符、布尔、void、枚举),则初始化列表最多包含一个值。
赋值运算 满足右结合律,赋值运算的结果是他的左侧运算对象,且是一个左值,当赋值运算符左右两侧的类型不同,右侧的转换为左侧的类型
int i,j;
i=j=0;//靠右的赋值运算j=0作为靠左的赋值运算符的右侧运算对象。
//赋值运算返回左侧运算对象,靠右的赋值运算的结果(j=0)赋给i
int i,*p;
i=p=0;//错误,p是指针,不能作为右值赋给int型的i
赋值运算符的优先级较低,与其他运算符混用时,应该注意加括号。
int i=0,j;
j=++i;//i=1,j=1
j=i++;//i=2,j=1
前置得到相加之后的值
后置得到相加之前的值
尽量用前置版本,当既需要把某一个值加1,且还要使用加之前的值,使用后置版本。
后置的递增运算符的优先级高于解引用运算符:
递增运算符改变了某个运算对象的值,所有在复合语句中,要小心使用,注意运算顺序。
*beg = toupper(*beg++);//错误,赋值语句左右都用到了beg,右侧又改变了beg,
*beg=toupper(*beg);
++beg;
成员访问运算符:
点运算 . 和箭头运算 -> 都可以访问 成员
(*p).men() 等价于 p->men()
条件运算符:满足右结合律
即三目运算符:?:
条件?表达式1:表达式2
条件成立返回表达式1,不成立返回表达式2
可以嵌套,不宜超过3层
(grade>90)?“youxiu”:(grade>60)?“pass”:failed"
注:输入输出的<< >>等是标准IO库对位运算符的重载,这两种运算符的内置含义是对其运算对象进行基于二进制位的移动操作。
令左侧运算对象的内容按照 右侧运算对象的要求移动指定的位数(可能会进行类型提升),将移动后的左侧运算对象作为求值结果。右侧运算对象不能为负,且值必须小于结果(有可能进行提升)的位数。
位求反运算符:逐位求反
位与、位或:逐位求与或者或
位异或:逐位,对应位置有且只有一个为1 ,则该位结果为1 .
移位运算符:优先级与结合律
满足左结合律。比算数运算符优先级低,比关系运算符、赋值运算符、条件运算符优先级高。
1)对char类型的使用sizeof,结果为1
2)对引用类型使用,结果为被引用对象所占空间的大小
3)对指针使用,指针本身所占的空间大小。本机器为8,无论是指向int还是double,还是数组。
4)对解引用的指针使用,指针所指向的对象所占的空间大小
5) 对数组使用,整个数组所占的空间大小,等价于把整个数组中的元素分别sizeof,在求和,
6)对string、vector 使用,得到该类型固定部分的大小,对本机器string为32,vector为24.
#include
#include
#include
#include
#include
using namespace std;
int main()
{
string s1("aav");//使用括号,只能有1个“ ”,string s{"hah","hha"}错误
string s2("hahh hahs");//sizeof后,string对象的固定大小32
cout<<"s2="<<s2<<endl;//输出的带空格即:s2=hahh hahs
vector <int> v1{0,1,2,3};//sizeof后,vector固定大小24
vector <string> v2{"string","hah","hehe"};//固定大小24
int ch1[]={0,1,2,3};//数组以逗号隔开
int ch2[3][4]={0,1,2,3,2,3,4,5,3,4,5,6};//多维数组以逗号隔开,每一维可以使用花括号扩起来
char ch3[]={'a','b','c', 'd'};//字符数组,没有最后的空字符串结束,不是c风格字符串
char ch4[]={"hah adsoaj !"};//c风格字符串,末尾有空字符结束符。
string ch5[]={"haha","heheh"};//string类数组,字符串数组
string ch6[4]={"haha","heheh"};//字符串数组
cout<<"bool="<<sizeof(bool)<<endl;//1
cout<<"char="<<sizeof(char)<<endl;//1
cout<<"wchar_t="<<sizeof(wchar_t)<<endl;//4
cout<<"char16_t="<<sizeof(char16_t)<<endl;//2
cout<<"char32_t="<<sizeof(char32_t)<<endl;//4
cout<<"short="<<sizeof(short)<<endl;//2
cout<<"int="<<sizeof(int)<<endl;//4
cout<<"long="<<sizeof(long)<<endl;//8
cout<<"long long="<<sizeof(long long)<<endl;//8
cout<<"float="<<sizeof(float)<<endl;//4
cout<<"double="<<sizeof(double)<<endl;//8/
cout<<"long double="<<sizeof(long double)<<endl;//16
cout<<endl<<"string s1="<<sizeof(s1)<<endl;//32
cout<<"string s2="<<sizeof(s2)<<endl;//32
cout<<endl<<"vector v1="<<sizeof(v1)<<endl;//24
cout<<"vector v2="<<sizeof(v2)<<endl;//24
cout<<endl;
cout<<"shuzu1="<<sizeof(ch1)<<endl;//4(int)*4(个元素)=16
cout<<"shuzu2="<<sizeof(ch2)<<endl;//4(int)*m*n(维度)=48
cout<<"shuzu3="<<sizeof(ch3)<<endl;//1(char)*4=4
cout<<"shuzu4="<<sizeof(ch4)<<endl;//13,字符串内容(包含空格)+末尾结束符
cout<<"字符串数组"<<sizeof(ch5)<<endl;//32*2=64
cout<<"字符串数组"<<sizeof(ch6)<<endl;//32*4=128
return 0;
}
指针、引用相关的sizeof:
#include
#include
#include
#include
#include
using namespace std;
int main()
{
string s1("aav");//
string s2("hahh hahs");
vector <int> v1{0,1,2,3};
vector <string> v2{"string","hah","hehe"};
int ch1[]={0,1,2,3};//数组以逗号隔开
int ch2[3][4]={0,1,2,3,2,3,4,5,3,4,5,6};//多维数组以逗号隔开,每一维可以使用花括号扩起来
char ch3[]={'a','b','c', 'd'};
char ch4[]={"hah adsoaj !"};
int a=8,*p1;
double y=3.13;
int &r=a;//
double &r2=y;//
int (&r3)[4]=ch1;//维度不能少,否则不能编译
int *p2=ch1;
int *p3=ch2[2];//
char *p4 = ch3;
char *p5 = ch4;
// 注意,string和vector使用下标和迭代器,不使用指针。c风格字符串
//可以使用指针,指针的类型不能是string啥的,只能是int double啥的。
cout<<*p2<<" "<<p2<<endl;
cout<<*p3<<" "<<p3<<endl;
cout<<*p4<<" "<<p4<<endl;
cout<<*p5<<" "<<p5<<endl;
cout<<r<<endl;
cout<<r2<<endl;
cout<<r3<<endl;//绑定数组的引用
cout<<*(r3)<<endl;//输出该数组第一个元素0
cout<<endl;
cout<<endl<<"string s1="<<sizeof(s1)<<endl;
cout<<"string s2="<<sizeof(s2)<<endl;
cout<<endl<<"vector v1="<<sizeof(v1)<<endl;
cout<<"vector v2="<<sizeof(v2)<<endl;
cout<<endl;
cout<<"shuzu1="<<sizeof(ch1)<<endl;
cout<<"shuzu2="<<sizeof(ch2)<<endl;
cout<<"shuzu3="<<sizeof(ch3)<<endl;
cout<<"shuzu4="<<sizeof(ch4)<<endl;
cout<<"int *="<<sizeof(p1)<<endl;//8,指针本身的大小为8
cout<<"zhixiangshuzu de zhizhen "<<sizeof(p2)<<endl;//8,同上
cout<<"zhixiang duowei shuzu de zhizhen="<<sizeof(p3)<<endl;//8,同上
cout<<"zhixiang zifu shuzu de zhizhen"<<sizeof(p4)<<endl;//8
cout<<"c fengge zifuchuan de zhizhen "<<sizeof(p5)<<endl;//8
cout<<endl;
cout<<"yinyong "<<sizeof(r)<<endl;//4引用的对象是int
cout<<"yinyong "<<sizeof(r2)<<endl;//8,引用的对象是double
cout<<"yinyong 3"<<sizeof(r3)<<endl;//316???为什么?
return 0;
}