[C++]“=”详解
引言
C++的“=”实际有很多很多陷阱。
在大部分情况下,“=”表示赋值,尤其是C语言学过来的,更有这样的体会。以下两者的执行结果是等效的:
// 示例A int a = 3; // 示例B int a; a = 3;
难免会有直观的认识,int a = 3 中,首先创建一个int的名为a的对象,然后将3赋值给a。而示例B中,将这一过程拆分成了两部。
↑↑恩,万恶的根源↑↑
C++中“=”的语义分类
“=”其实有两种作用:1. 参与构造;2. 赋值。
参与构造类似于初始化,是狭义的初始化(或者是说协助定义,异或有其他更好的说法?)——在一些场合,对从未赋值过的对象进行第一次赋值,也叫做初始化——而这里的“初始化”仅指构造完成对象的这一过程。
// 传统意义上的初始化
int a; // 定义了一个对象←其实是内置类型,C++好绕啊=_=
a = 3; // 对其初始化←实际上就是赋值了而已
// 本文所说的初始化和赋值
int a; // 定义了一个对象←其实已经构造完毕了,因为没用=,所以默认初始化的
// 有的情况下,默认初始化为了0xCDCDCDCD
// 有的情况下,默认初始化为了内存存放的旧值
a = 3; // 对于赋值
以下的例子说明了int a = 3; 和 int a; a = 3; 是不一样的:
static int func1_i; // static duration变量默认为0
int func1(){
static int i = func1_i; // 这里的=参与的是初始化
// 因为static的函数成员只在第一次使用时构造,
//所以只执行了1次
return i++;
}
static int func2_i;
int func2(){
static int i; // 同上,这一句只执行1次
i = func2_i; // 这是赋值,每次都要执行
return i++;
}
int main(int argc, char* argv)
{
using namespace std;
cout << func1();
cout << func1() << endl; // 输出 01
cout << func2();
cout << func2() << endl; // 输出 0 0,因为每次都重新赋值为0
getchar();
}
这一问题,在C中并不显著,但是在C++却很重要,因为——C++有对象(C你就继续单身着吧)
除了赋值,还有构造
对于内置类型,是无法探寻其实现代码的,C++保证语义上符合这一归于。但是对于用户定义的类就不一样了,我们可以自己书写代码,来验证这一语义。
struct A{
// 默认构造函数
A() {std::printf("default ctor\n");}
// 隐式转换构造函数
A(int) {std::printf("ctor with para int\n");}
// 赋值
A& operator=(int) {std::printf("operator=\n"); return *this;}
};
int main(int argc, char* argv)
{
using namespace std;
A a1; // 输出default ctor,调用了默认构造
a1 = 3; // 输出operator=,调用了赋值
A a2 = 3; // 输出ctor with para int,调用了带参数的构造
getchar();
}
切记,ClassA obj = value; 绝不是创建一个对象obj,然后把value赋值给obj那么简单。
注意类型转换
上边例子的赋值3,可以改为浮点数,编译器会尝试将浮点数转为整数,然后调用响应的函数。
但是,如果存在转换不了的情况,例如string到int,编译器则会报错。
struct A{
A() {std::printf("default ctor\n");}
A(int) {std::printf("ctor with para int\n");}
A& operator=(int) {std::printf("operator= with para int\n"); return *this;}
// 书写了一个无法转换为int的参数的类型
A& operator=(std::string) {std::printf("operator= with para string\n"); return *this;}
};
int main(int argc, char* argv)
{
using namespace std;
string str = "str";
A a1; // 默认构造
a1 = str; // 输出operator= with para string赋值
A a3 = str; // 报错,提示没有这种类型的ctor不存在,需要一个A(string)的构造函数
getchar();
}

浙公网安备 33010602011771号