为什么复制构造函数被调用?

时间:2020-06-14 10:05:38

标签: c++ c++11

我有以下代码,其中有几件事最让我感到困扰:

  1. 原始构造函数调用在什么时间发生?
  2. 在哪种情况下,将调用副本构造函数?
#include <iostream>
#include <functional>

class Samp {
    char str[10] = "Default";
public:
    Samp(char s[]) { strcpy(str, s); printf("Constructor\n"); }
    Samp(const Samp& s) { printf("Copy Constructor\n"); }
    ~Samp() { printf("Destructor\n"); }

    char* out() {
        return str;
    }

    friend std::ostream& operator<<(std::ostream& stream, const Samp& s) {
        stream << s.str;

        return stream;
    }
};

void output(Samp s) {
    std::cout << s << std::endl;
}

int main(int argc, const char * argv[]) {
    std::function<void(Samp s)> o;
    o = output;

    o((char*)"Hello");

    return 0;
}

在执行时,程序将提供以下输出

Constructor
Copy Constructor
Default
Destructor
Destructor
Program ended with exit code: 0

enter image description here

3 个答案:

答案 0 :(得分:5)

perfect forwardingstd::function调用的参数传递给存储在std::function对象内部的可调用对象。

因此o(args...)的行为与output(args...)不同。相反,它与:

output( std::forward<Args...>(args...) );

或者在这个具体示例中,

output( std::forward<Samp>( (char *)"Hello" ) );

在此示例中,我们看到“完美”的转发不是那么完美,因为此代码的行为与output( (char *)"Hello" );略有不同。

forward选择的重载的签名为Samp&& forward(Samp&& arg);。因此,对于arg,必须有一个临时实体才能绑定到std::forward;那就是您看到的“构造函数”。

然后,“复制构造函数”是根据output的返回值初始化std::forward函数的参数。如果Samp具有移动构造函数,则可能是移动操作。

答案 1 :(得分:2)

您的类的构造方法和复制方法基本上在一个地方调用。 使用您的函数时,将通过构造创建Samp S,然后将其复制到void fnc。

答案 2 :(得分:2)

void output(Samp s)

这是问题所在。此函数按值传递对象。致电

o((char*)"Hello")

,它将通过默认构造函数创建一个临时的Samp对象,并通过复制构造函数创建另一个新对象以传递给该函数。

相关问题