复制构造函数并返回传递的参数

时间:2018-03-27 08:33:02

标签: c++ constructor copy-constructor

我正在阅读Prata的C ++书籍,在谈论复制构造函数时,它表示在以下情况下调用此构造函数:

  1. 将类对象初始化为相同类型的类对象。
  2. 按值将对象传递给函数。
  3. 按函数从值返回对象。
  4. 假设我们正在使用Vector类。

    为了理解sakes,在本章的示例中,我们在构造函数/析构函数定义中包含了字符串输出,以指示调用它们的时间和时间。

    例如,如果我们有

    int main()
    {
    
        Vector v1;          // print "Default constructor called"
        Vector v2(9, 5);    // print "Constructor called"
        Vector v3 = v1;     // print "Copy Constructor called"
    
        return 0;
    }
    

    退出Destructor called时,main()将在此案例中打印3次。

    为了检查以上3点,我一直在玩dumb_display()功能,更改形式参数/返回值的类型。在这样做的过程中,我对实际发生的事情感到困惑。

    Vector dumb_display(Vector v)
    {
        Vector test(45, 67);
        cout << "In dumb_display() function" << endl;
        cout << v << endl;
        return v;
    }
    

    下面:

    • 每次按值返回传递的参数,如上面的函数(由值或引用传递的参数),复制构造函数被调用。

      • 这很有道理。它满足第3点。

    每次我们返回函数体中定义的对象(例如,return v;更改return test;)时,都不会调用复制构造函数。

    • 第3点并不满意。

    我很难尝试理解这种行为。

    我不知道这是否正确,但我认为(因为在函数调用期间创建了一次自动存储持续时间对象)一旦test被创建,它就不会出现。必须再次创建,因为对象&#34;已经存在&#34;。这带来了一个问题:

    为什么返回传递的参数会调用复制构造函数两次?为什么在调用函数期间必须创建两次相同的对象?

2 个答案:

答案 0 :(得分:0)

#include <vector>
#include <type_traits>
#include <tuple>
#include <iostream>

using namespace std;

struct S {
    S(){
        cout << "default constructor" << endl;   
    }
    S(S const &) {
        cout << "copy constructor" << endl;
    }
    S(S &&) {
        cout << "move constructor" << endl;
    }
    S & operator=(S const &) {
        cout << "copy assignment" << endl;
        return *this;
    }
    S & operator=(S &&) {
        cout << "move assignment" << endl;
        return *this;
    }
};

S f() {
    S s2;
    cout << "In f()" << endl;
    return s2;
}

S f2(S s) {
   cout << "In f2()" << endl;
   return s;
}

int main() {
    cout << "about to call f" << endl;
    S s2 = f();
    (void)s2;

    cout << endl << "about to call f2" << endl;
    S s3 = f2(s2);
    (void)s3;
}

结果:

about to call f
default constructor
In f()

about to call f2
copy constructor
In f2()
move constructor

f()中,对象是默认构造的,并且返回值优化用于实际构建它实际上最终的位置 - 在main中的s2变量中。不会调用复制/移动构造函数。

f2()中,为该函数的输入参数创建一个副本。然后将该值移入main中的变量s3,再次使用返回值优化。

直播:https://wandbox.org/permlink/kvBHBJytaIuPj0YN

如果您关闭返回值优化,您会看到您对图书所说的结果:

直播:https://wandbox.org/permlink/BaysuTYJjlJmMGf6

以下是没有move运算符的两个示例,如果这让您感到困惑:

直播:https://wandbox.org/permlink/c0brlus92psJtTCf

并且没有返回值优化:

直播:https://wandbox.org/permlink/XSMaBnKTz2aZwgOm

它是相同数量的构造函数调用,只使用(可能更慢)复制构造函数而不是移动构造函数。

答案 1 :(得分:-1)

复制构造函数被调用两次,因为它首先从函数复制到temprary值(由函数调用表示并且是返回值,然后复制到变量中,需要两个副本。因为这是效率不高,还有一个“移动”构造函数,只需要一次。