这是一个简单的例子:
class A {
public:
A() {
printf("%p C1\n", this);
}
A(const char* p) {
printf("%p C2\n", this);
}
};
int main(int argc, char *argv[]) {
A a;
a = "abc";
}
在代码中,尽管A
仅被声明一次,但有两个A
实例被创建。构造函数被调用两次。我可以在VS 2013和gnu C ++中重现这一点。
想知道这种行为是错误还是规范的一部分。
答案 0 :(得分:6)
这是规范的一部分。当你这样做时:
a = "abc";
使用A
构造函数在RHS上的"abc"
表达式创建临时A(const char* p)
对象。这用于将值分配给a
。
如果你这样做了
A a = "abc";
你只能看到一个构造函数调用。
答案 1 :(得分:4)
因为您没有禁用自动生成的赋值运算符或复制构造函数,所以您的类实际上对编译器来说是这样的:
class A {
public:
A() {
printf("%p C1\n", this);
}
A(const A& rhs) { }
A(const char* p) {
printf("%p C2\n", this);
}
A& operator=(const A& rhs) { return *this; }
};
因此a = "abc"
被解释为a.operator=( A("abc") )
它期望const A&
作为operator=
的参数,它可以构造,因为您提供了构造函数A(const char*)
。
您可以通过使构造函数显式来阻止意外转换。
class A {
public:
A() {
printf("%p C1\n", this);
}
explicit A(const char* p) {
printf("%p C2\n", this);
}
};
然后这应该无法编译:
int main(int argc, char *argv[]) {
A a;
a = "abc";
}
除非您明确构建:a = A("abc");