C++ 为什么要调用复制构造函数?

C++ 为什么要调用复制构造函数?,c++,c++11,C++,C++11,我有以下一段代码,其中有两件事最让我困扰: 原始构造函数调用发生在什么时间点? 在什么情况下调用复制构造函数? 构造函数和类的副本基本上在一个地方调用。 当你使用你的函数时,通过构造创建Samp,然后将其复制到void fnc void output(Samp s) 这就是问题所在。此函数按值传递对象。当你打电话的时候 o((char*)"Hello") ,它通过默认构造函数创建一个临时Samp对象,并通过复制构造函数创建另一个新对象以传递给函数。调用std::function的参数通过传递

我有以下一段代码,其中有两件事最让我困扰:

  • 原始构造函数调用发生在什么时间点?
  • 在什么情况下调用复制构造函数?

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

    void output(Samp s)
    
    这就是问题所在。此函数按值传递对象。当你打电话的时候

    o((char*)"Hello")
    

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

    调用
    std::function
    的参数通过传递给存储在
    std::function
    对象中的可调用对象

    因此,
    o(args…
    的行为与
    输出(args…
    不同。相反,它与:

    output( std::forward<Args...>(args...) );
    
    输出(std::forward(args…);
    
    或者在这个具体的例子中

    output( std::forward<Samp>( (char *)"Hello" ) );
    
    输出(std::forward((char*)“Hello”);
    
    在本例中,我们看到“完美”转发并不完美,因为此代码的行为与
    输出((char*)“Hello”)略有不同

    forward
    选择的重载的签名是
    Samp&&forward(Samp&&arg)。因此,对于对
    std::forward
    的函数调用,
    arg
    必须绑定到一个临时物化的对象;这就是你看到的“构造器”


    然后,“复制构造函数”是从
    std::forward
    的返回值初始化
    输出
    函数的参数。如果
    Samp
    有一个move构造函数,那么这可能是一个move操作。

    为什么不一步一步地调试,看看哪个语句给出了哪个输出?我想你很难得到它,因为所有的输出都是由
    o((char*)“Hello”)
    生成的。所以我建议您在使用printf的地方放置断点。然后一步一步地调试谢谢@Nitesh,我已经做了一些调查,结果表明,在堆栈帧被破坏后,确实在第38行调用了原始构造函数,然后执行返回到第38行,之后调用了“o”函数,但对象构造是由于调用了复制构造函数,这就是我想要得到的,是什么机制导致了这种情况发生原始构造函数调用正在将
    (char*)“Hello”
    转换为
    Samp
    。然后调用复制构造函数,因为第一个构造的对象是通过值复制到
    输出的。请注意,复制构造函数不会更改
    str
    成员,因此打印它会生成
    Default
    。然后,在控件到达
    main()
    中的
    返回0
    之前,这两个对象被销毁。根据编译器的使用年限,可能会出现省略临时变量的情况——但是,从您描述的输出来看,不会出现省略。太棒了!谢谢你,彼得,现在我明白了。最初,我认为输出((char*)“Hello”);和o((char*)“你好”);,因为直接调用“output”不会导致创建临时对象。谢谢!我已将“output”函数的签名更改为:void output(const Samp&s);它是有效的。您能否解释一下,为什么首先要创建这个临时对象?因为输出函数需要一个Samp对象,而不是char*,所以它通过Samp(char[])创建一个临时对象,我认为这不是一个好的答案,因为
    output((char*)“Hello”)不创建任何临时文件。函数参数由
    char*
    初始化,不涉及中间对象。答案应该解释
    输出((char*)“Hello”)
    o((char*)“Hello”)。而且Samp类甚至没有默认构造函数,因此您的语句“it creates a temporary Samp object by default constructor”无法更正。我同意@M.M。理想情况下,函数签名将通过使用char[]的构造函数创建Samp对象。没有涉及副本。这个问题与std::function有关。
    
    output( std::forward<Args...>(args...) );
    
    output( std::forward<Samp>( (char *)"Hello" ) );