3.2 string
直接初始化和拷贝初始化
如果使用**=**
初始化一个变量,实际上执行的是拷贝初始化,编译器将=
右边的初始值拷贝到新创建的对象中。如果不使用**=**
,则执行直接初始化。
HINT:拷贝初始化不支持调用explicit
构造函数。
注意:
3.5.3 指针与数组
使用数组的时候,编译器通常把它们当作指针。
在一些情况下,数组的操作实际上是指针的操作,当使用一个数组作为**auto**
变量的初始值,推导得到的类型是指针而非数组。
两个指针相减的结果是它们的距离,一种名为ptrdiff_t
的类型(有符号)。参与运算的两个指针必须指向同一个数组当中的元素。
4.1.3 求值顺序
只有四种运算符明确规定运算对象的值:&&
、||
、?:
和,
。
求值顺序、优先级、结合律
即函数的调用顺序没有严格规定,不一定~
4.4 赋值运算符
赋值运算的结果是它的左侧运算对象,并且是一个左值。结果的类型就是左侧运算对象的类型。如果赋值运算符左右两侧对象类型不同,则右侧对象将转换成左侧运算对象的类型:
4.9 sizeof 运算符
sizeof
有两种使用方式:
sizeof(type)
sizeof expr
第二种形式返回的是表达式结果类型的大小。而**sizeof**
并不实际计算其运算对象的值。
#include <iostream>
using namespace std;
struct A {
int a;
int b;
int c;
};
int main() {
A* a = new A();
cout << "pointer size:" << sizeof(a) << endl;
cout << "object size:" << sizeof *a << endl;
return 0;
}
HINT:
sizeof
作用的解引用指针不需要是有效指针,因为sizeof
不对其求值。- 对数组执行
**sizeof**
操作得到整个数组的大小,等价于对数组中所有元素各执行一次sizeof
运算并求和。**sizeof**
不会将数组转换成指针操作。所以这种情况利好char c[]="..."
,而不利于char* c = "...."
。 - 对
**string**
和**vector**
对象执行**sizeof**
操作只返回该类型固定部分的大小,不会计算对象中元素占用了多少空间。
4.10 逗号运算符
逗号运算符包含两个运算对象,按照从左到右的顺序依次求值。先对左侧对象求值,然后将该值丢弃,逗号运算符真正的结果是右侧表达式的值。
4.11 隐式转换
- 数组转换成指针:在大多数用到数组的表达式中,数组自动转换成指向首元素的指针:
当使用decltype
、或者作为取地址符(&
)、sizeof
和typeid
等运算符的运算对象时,上述转换不会发生。
- 指针的转换:常量整数值0,或者字面值
nullptr
能转换成任意指针类型。指向非常量的指针可以转换为void *
,指向常量的指针可以转换为const void *
, - 转换成常量:允许将指向非常量的指针转换成相应的常量指针,对引用亦然。相反的转换不存在,因为试图删除底层
const
。