为什么没有调用复制构造函数

Why copy constructor is not invoked?

本文关键字:复制 构造函数 调用 为什么      更新时间:2023-10-16

抱歉,标题过于模糊。(因为我的英语水平不高)。请建议一个更好的标题。

请考虑下面的代码。

struct A {
    typedef std::vector<double> State;
    //  template <class... Args>
    //  A(Args... args)
    //      : a(args...)
    //  {}
    template <class... Args>
    A(Args&&... args)
            : a(std::forward<Args>(args)...)
    {}
    A(const A&) = default;
    A(A&&) = default;
    State a;
};
int main(){
    A a(3,2);
    A b = a; // This line triggers an error!!
}

Gcc 4.8.0编译失败,并显示错误信息error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...) .

我不明白为什么这段代码是错误的。在我看来,编译器应该调用A b = a;行中的复制构造函数。

但是,如果我将构造函数替换为注释过的构造函数(它只接受值)。它确实可以编译。此外,现在不需要用于默认复制(和移动)构造函数的行。这里发生了什么?

在c++ 11中,让编译器自动推断模板参数(就像你必须用模板化的构造函数那样),并将&&应用于类型,创建一个通用引用,它匹配任何具有任何cv资格的类型,无论是左值引用还是右值引用。

所以在你的情况下,你在传递一个A,因此Args... = A &, Args &&... = A & &&,这是A &多亏了引用崩溃规则,这是一个比const A &更好的匹配,因为编译器不需要添加constness到一个非const变量。

我认为在这种情况下模板构造函数是一个更好的匹配,因为它接受非const值。如果你把a改成const,它会调用复制构造函数…

const A a(3,2);
A b = a;