前缀递增和后缀递增
class NewInt
{
public:
NewInt():RootInt(0){};
NewInt(int IniInt):RootInt(IniInt){};
NewInt& operator++()
{
cout<<"prefix"<<endl;
this->RootInt+=1;
return *this;
}
NewInt operator++(int) //后缀,对参数(int)不要疑惑,int没有实质的作用,仅仅是为了区别前缀方式,标志这个++操作符是后缀形式
{
cout<<"postfix"<<endl;
NewInt preNum = *this; //后缀递增操作中,先要保存原对象到一个对象中这里采用的前缀式中方法;
++(*this); //然后对原对象进行递增操作 ;
return preNum; //最后返回原来保存的元对象。
}
private:
int RootInt;
};
来源: http://blog.csdn.net/tian_jinping/article/details/9706857
在后缀递增的时候,会先保存一个原对象,然后对原对象递增,再返回原对象。
所以用前缀递增效率更高一点,后置类型有时候是一种浪费。
例:
++a = 22;里面先++a,返回的东西是 a, 而a是一个变量,显然是一个是一个左值,他可被程序寻址,可以改变它的值
a++呢?a++是一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值,所以它是右值,不是左值
a++呢?a++是一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值,所以它是右值,不是左值
复合运算符:
a+=b(a=a+b)任何一个都可等效于 a = a op b
但是复合运算只需要求值一次,普通的则需要求值两次。
一次是作为右边表达式的求值,另一次是作为赋值运算的左侧运算的求值。
成员运算符:
箭头作用于指针类型的对象,结果是一个左值。
点运算符分成两种情况,成员所属对象是什么值,则返回什么值
条件运算符:
cout<<((it == vec.end())?"no":"yes")<< endl;
/*如果两个表达式都是左值或者能转换成同一种左值 返回左值*/
sizeof运算符
其所得是一个size_t类型,由于并不实际计算对象值,所以指针无效也可以。。。
而且不会把数组转换成指针,返回的是整个数组所占的大小
sizeof(ia)/sizeof(*ia)就能返回数组大小
1 sizeof(type) 2 sizeof expr //返回表达式类型的大小 3 Sale_data data; 4 sizeof date; //data类型的大小,即sizeof(Sales_data);
sizeof *p因为右结合律并且与*的优先级一样,所以表达式按从右到左组合。于是等价于sizeof(*p);
结构体的sizeof:
结构体的sizeof涉及到字节对齐问题。
为什么需要字节对齐?有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,依次类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。
字节对齐的细节和编译器的实现相关,但一般而言,满足三个准则:
(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除。
(2)结构体的每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要,编译器会在成员之间加上填充字节(internal adding)。
(3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员后加上填充字节(trailing padding)。
注意:空结构体(不含数据成员)的sizeof值为1。试想一个“不占空间“的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢,于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。
参考:http://blog.csdn.net/candyliuxj/article/details/6307814
struct node { int val = 0; char name = ' '; int i = 0; }; int main() { node root; cout << sizeof(root) << endl; system("pause"); }