复制构造函数每次调用默认构造函数? [英] Copy constructor called everytime a default constructor is called?

查看:216
本文介绍了复制构造函数每次调用默认构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



考虑这个:


$ b $

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

现在,请查看:


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


资料来源:

这是什么意思?当我调用无参数构造函数时,复制构造函数也被调用。



请解释。这真的很混乱。



特别是第一行的意义:


当您进入构造函数体时,所有字段都已经构建完毕



解决方案

这意味着在你到达 id = 0 之前, int id 因为没有指定明确的初始化程序,所以它已被默认初始化。另外,因为它是一个 int ,初始化规则告诉使用它将有一些不确定的值。



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



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

  #include< iostream> 

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

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

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

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

〜Verbose(){
std :: cout< __PRETTY_FUNCTION__<< \\\
;
}
};

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. 请注意,我们基本上构造了 Verbose v 两次!我们首先使用默认构造函数,然后我们基本上使用 operator = 调用重建它。如果我们使用初始值设置列表,我们可以将其减少到一次调用 Verbose(int)


    I was going through some of the questions on constructor initialization list when I bumped into this.

    Consider this:

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

    Now, check this out:

    By the time you get in the body of the constructor, all fields have already been constructed; if they have default constructors, those were already called. Now, if you assign a value to them in the body of the constructor, you are calling the copy constructor. That is inefficient, because two constructors end up being called instead of one.

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

    So, does it mean that when I call the parameter-less constructor, the copy constructor is also being called?

    Please explain. This is really confusing.

    Particularly the meaning of the first line:

    By the time you get in the body of the constructor, all fields have already been constructed

    解决方案

    It means that int id has already been initialized before you get to the line id = 0. Because no explicit initializer has been specified, it has been default initialized. Additionally, because it is an int, the initialization rules tell use that it will have some indeterminate value.

    In practice, for an int, or any type that is extremely cheap to initialize, this doesn't matter too much.

    If instead of using an int member, we used a class, we could more clearly see what is actually going on behind the scenes:

    #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;
    }
    

    This code will output:

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

    Note that we:

    1. We use the default constructor to create v.
    2. We create a temporary Verbose(3)
    3. We then use the assignment operator to assign the temporary to the member variable.
    4. We then destroy the temporary.
    5. When Object o goes out of scope, we then destroy the member variable.

    Note that we basically constructed Verbose v twice! We first used the default constructor, and then we basically rebuilt it using the operator= call. If we used an initializer list, we could reduce that down to one call to Verbose(int).

    这篇关于复制构造函数每次调用默认构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆