每次调用默认构造函数时调用的复制构造函数?

时间:2015-02-15 18:17:36

标签: c++

当我碰到这个问题时,我正在浏览构造函数初始化列表中的一些问题。

考虑一下:

class Student {
    public:
        Student() {
            id = 0;
        }
        Student(int i) {
            id = i;
        }
    private:
        int id;
};

现在,看看这个:

  

当你进入构造函数的主体时,所有字段都已构建;如果他们有默认的构造函数,那些已经被调用。现在,如果在构造函数的主体中为它们赋值,则调用复制构造函数。这是低效的,因为两个构造函数最终被调用而不是一个。

来源:What does a colon following a C++ constructor name do?

那么,这是否意味着当我调用无参数构造函数时,也会调用复制构造函数?

请解释一下。这真令人困惑。

特别是第一行的含义:

  

当你进入构造函数的主体时,所有字段都已构造

2 个答案:

答案 0 :(得分:4)

这意味着int id在您到达id = 0行之前已经初始化了。由于未指定显式初始值设定项,因此已对其进行了默认初始化。另外,因为它是int,初始化规则会告诉我们它会有一些不确定的值。

在实践中,对于int或任何初始化非常便宜的类型,这并不重要。

如果不使用int成员,我们使用了一个类,我们可以更清楚地看到幕后实际发生的事情:

#include <iostream>

class Verbose {
    public:
        Verbose() {
            std::cout << __PRETTY_FUNCTION__ << "\n";
        }

        Verbose(int) {
            std::cout << __PRETTY_FUNCTION__ << "\n";
        }

        Verbose(Verbose const &) {
            std::cout << __PRETTY_FUNCTION__ << "\n";
        }

        Verbose & operator=(Verbose const &) {
            std::cout << __PRETTY_FUNCTION__ << "\n";
            return *this;
        }

        ~Verbose() {
            std::cout << __PRETTY_FUNCTION__ << "\n";
        }
};

class Object {
    public:
        Verbose v;

        Object() {
            v = Verbose(3);
        }
};

int main() {
    Object o;
}

此代码将输出:

Verbose::Verbose()
Verbose::Verbose(int)
Verbose &Verbose::operator=(const Verbose &)
Verbose::~Verbose()
Verbose::~Verbose()

请注意我们:

  1. 我们使用默认构造函数来创建v
  2. 我们创建了一个临时Verbose(3)
  3. 然后我们使用赋值运算符将临时值分配给成员变量。
  4. 然后我们销毁临时的。
  5. Object o超出范围时,我们会销毁成员变量。
  6. 请注意,我们基本上构建了Verbose v两次!我们首先使用默认构造函数,然后我们基本上使用operator=调用重建它。如果我们使用initializer list,我们可以将其减少到一次调用Verbose(int)

答案 1 :(得分:3)

他们的意思是

Student() {
    id = 0;
}

效率低于

Student() : id(0) {}

在此特定示例中,id将在一个步骤中初始化,因为该成员只是int

相比之下,如果Student具有更复杂的成员,如BackpackBooks,则后一种方法会有所不同。如果这些类不是POD,第一种方法将采用两个步骤来初始化成员,第二种方法只需要一步来初始化。