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

10

非常抱歉标题表述不够明确(由于我的英语水平有限)。请建议一个更好的标题。

请考虑以下代码。

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;这一行中,编译器应该调用拷贝构造函数。

然而,如果我将构造函数替换为注释掉的那个(它只是简单地接受值),那么它可以编译。此外,现在默认的拷贝(和移动)构造函数的行也不再需要了。这里发生了什么?

2个回答

9
在C++11中,编译器可以自动推导模板参数(就像你必须使用模板构造函数一样),并将&&应用于类型,创建通用引用,该引用与任何带有任何cv限定符的类型匹配,无论它是左值还是右值引用。
因此,在您的情况下,您正在传递一个A,因此Args...=A &Args &&...=A & &&,由于引用折叠规则,这是A &,这比const A &更匹配,因为编译器不必向非const变量添加constness。

3
我认为在这种情况下,模板构造函数更加匹配,因为它需要非 const 值。如果你将 a 更改为 const,那么它会调用拷贝构造函数...
const A a(3,2);
A b = a;

如果我添加另一个复制构造函数 A(A&) = default,它可以编译通过。 :) - Sungmin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接