实例化类的正确方法

时间:2014-03-26 12:38:25

标签: c++

这两种实例化类的方式都可以接受吗? 我的目的是在堆栈上创建CBox而不是堆

CBox a=CBox(1);
CBox b(2);

CBox的定义如下:

class CBox
{
public:
    int abc;
    CBox(int var){
        abc=var;
    }

};

3 个答案:

答案 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会同意,或建议编辑。]

在回答问题时,使用哪个取决于可读性和其他因素。