05/11/2020
逗号运算符
先上一段代码,下面可以正常运行,请问最后打印结果是什么
class A
{
public:
A(int a=0,int b=0, int c=0)
:mA(a)
,mB(b)
,mC(c)
{
std::cout << mA <<" "<<mB<<" "<<mC;
}
//copy constructor
A(const A& a)
{
mA = a.mA;
mB = a.mB;
mC = a.mC;
}
private:
int mA;
int mB;
int mC;
};
int main(){
A a = (1,2,3); //3 0 0
A a2 = A(1,2,3); //1 2 3
}
如何看这段代码
调用带三个参数的构造函数。得到结果为1 2 3。.但是最后结果为3 0 0
隐式的类类型转换- 转换构造函数(converting constructor)
进一步猜测感觉a对象会是一个隐式转换,它会先调用转换构造函数。
先看下转换构造函数的定义:1
能通过一个实参调用的构造函数定义了一条从构造函数的承诺书类型向类类型隐式转换的规则。
- 具体来说就是传递一个实参并匹配到构造函数就行,并不是构造函数只有一个形参的形式。
提问:看到上面带参数的构造函数它到底是不是转换构造函数?
答案是的,因为A a = (1,2,3); 的确传递了一个实参,并且匹配到了一个构造函数,这个带3个参数的构造函数看起来并不能匹配,怪就怪在它的参数有默认初始值,所以也可以看成是带一个参数的构造函数。同时,它可能还是默认构造函数。
- 对带三个参数加上explicit修饰词,最后报错了。
神奇的逗号运算符
int a;
1,2,3,
a = 4;
std::cout << a; //结果是4;
语句2
乍一看上面的语法不对,应该回报错,但事实是通过了编译。什么是语句?
语句的特性:
- 语句是以分号为结尾,特殊的块语句不是分号结尾。
- 语句是可以通过编译的形式
; //空语句 -- 最简单的语句
;;//多余的空语句
while(true);
for(int i=0;i<5;i++);
if(4==5);
现在回头看看之前的语句的语法有没有问题,有没有分号?
int a;
1,2,3,a = 4; //换行只是为了美观,编译器检查语句会自动换到下一行去找分号。
std::cout << a; //结果是4;
遗留的逗号运算符3
- 逗号运算符含有两个运算对象,按照从左向右的顺序一次求值。和逻辑与、逻辑或一样,规定了求值顺序。
- 对于逗号运算符来说,首先对左侧的表达式求值,然后将求值结果丢弃掉,逗号运算符真正的结果是右侧表达式的值。
- 逗号运算符的优先级是最低的
- 可以被用来重载
回头再看看
A a = (1,2,3);
逗号运算符丢弃掉了前面的1和2,最后a拿到数字3调用转换构造函数。
建议改正写法:使用花括号
A a = {1,2,3}; //调用构造函数,不会隐式转换