这两种实例化类的方式都可以接受吗?
我的目的是在堆栈上创建CBox
而不是堆
CBox a=CBox(1);
CBox b(2);
CBox的定义如下:
class CBox
{
public:
int abc;
CBox(int var){
abc=var;
}
};
答案 0 :(得分:1)
事实上,由于第一个定义中复制/移动构造函数的省略,两个定义是等价的。
CBox a=CBox(1);
CBox b(2);
唯一的区别是,如果复制/移动构造函数不可访问或者可能不会被隐式调用(例如它是私有的或被定义为已删除或具有明确的函数说明符),那么除了MS VC ++之外不会编译第一个语句它有自己的语言扩展,通常只是编译器错误。:)。
答案 1 :(得分:0)
如果你有这样的课程定义:
class A
{
public:
int q;
A() {
std::cout << "Constructor without argument" << std::endl;
}
A(int x) : q(x) {
std::cout << "Constructor" << std::endl;
}
A(const A& a) {
std::cout << "Copy Constructor" << std::endl;
this->q = a.q;
}
A& operator=(const A& a) {
std::cout << "Assignment operator" << std::endl;
if(&a != this) this->q = a.q;
return *this;
}
};
然后您会得到以下结果:
int main(int argc, char** argv)
{
A a(2); // uses constructor
A b = A(3); // uses constructor (exact same as A b(3);)
A c = b; // uses copy constructor
A d; // uses constructor without parameter
c = d; // uses assignment operator
}
作为评论:在C ++ 11中,您还可以编写A a{2};
,这可以避免与函数调用的混淆。
总结一下:只需编写A a(2);
- 或者如果您使用的是C ++ 11 A a{2};
。
答案 2 :(得分:0)
该标准的相关部分是(n3797)8.5 / 17.
否则(即,对于剩余的复制初始化情况), 用户定义的转换序列,可以从源转换 键入目标类型或(使用转换函数时) 按照13.3.1.4的描述列举其派生类别, 并且通过重载决策(13.3)选择最好的一个。如果 转换不能完成或模糊,初始化是 病态的。使用初始化程序调用所选的函数 表达作为其论点;如果函数是构造函数,则调用 初始化一个临时的cv-nonqualified版本的 目的地类型。临时是一个prvalue。通话的结果 (然后用于构造函数的临时情况) 根据上面的规则,直接初始化对象 复制初始化的目的地。在某些情况下, 允许实现消除此中固有的复制 通过直接构造中间结果直接初始化 进入被初始化的对象;见12.2,12.8。
根据代码:
,意味着什么CBox a=CBox(1);
CBox b(2);
如果符合某些(合理的)条件,这两段代码将在符合标准的编译器中执行完全相同的操作。没有临时生成,没有赋值操作,也没有副本。在两种情况下,都会调用构造函数来直接初始化对象。
我发现标准不清楚这是copy elision
,因为这里没有使用该术语。它包含在12.8 / 31中。
[我没有回答这个问题,但遗憾的是其他所有答案都是错误的。我希望@Kerrek会同意,或建议编辑。]
在回答问题时,使用哪个取决于可读性和其他因素。