【问题标题】:competing implicit and template copy constructors竞争隐式和模板复制构造函数
【发布时间】:2012-12-17 11:59:59
【问题描述】:

关于this的帖子,请解释一下这种行为:

#include <stdio.h>

struct B { B(B&) { } B() { } };
struct A {
  template<typename T>
  A(T&){ printf("A(T&)\n"); }
  A() { }
//  B b; // when this is uncommented, output changes 
  int i;
};

int main() {
  A a;
  A b(a);

// B b; commented:
// template wins:
//   A<A>(A&)  -- specialization
//   A(A const&); -- implicit copy constructor
// (prefer less qualification)

// B b; uncommented:
// implicit copy constructor wins:
//   A<A>(A&)  -- specialization
//   A(A&); -- implicit copy constructor
// (prefer non-template)

  printf("\nA\n");
  A const a1;
  A b1(a1);

// B b; commented:
// implicit copy constructor wins: 
//   A(A const&) -- specialization
//   A(A const&) -- implicit copy constructor
// (prefer non-template)

// B b; uncommented:
// template wins:
//   A(A const&) -- specialization
// (implicit copy constructor not viable)
}

当 B b 时输出改变;未注释。

显然,当取消注释B b; 时,隐式复制构造函数从A(A const&amp;) 更改为A(A &amp;)。为什么?当我将B(B&amp;){} 更改为B(const B&amp;){} 时,复制构造函数又更改回A(A const&amp;)。现在编译器满意A() 的形参将是const?这跟标准有关系吗? (我使用的是 gcc 4.2.4。)

【问题讨论】:

    标签: c++ templates constructor copy implicit


    【解决方案1】:

    如果可行,类 A 的隐式复制构造函数的签名是 A(const A&amp;)。当您取消注释 B b; 行时,此复制构造函数不可行,因为 B 的复制构造函数需要一个非常量输入参数。

    // Illegal implicit copy constructor
    A::A(const A& a) :
    b(a.b),  // This line would be illegal because a.b is const
    i(a.i)
    {
    }
    

    在这种情况下,隐式复制构造函数也是非常量版本:A(A&amp;);

    // Legal implicit copy constructor
    A::A(A& a) :
    b(a.b),  // Fine: a.b is now non-const
    i(a.i)
    {
    }
    

    这就是在类定义中取消注释 B b; 会更改隐式复制构造函数并因此更改程序行为的原因。

    编辑:不直接相关,但为了完整起见:如果 B 没有可访问的复制构造函数(因为它被声明为 private 或已删除),A 将没有隐式复制构造函数。

    【讨论】:

      【解决方案2】:

      是的,这种行为在 12.8/8 标准中得到了很好的定义:

      X 的隐式声明的复制构造函数将具有X::X(const X &amp;) 的形式,如果[...条件有意义...],否则[它] 将具有X::X(X &amp;) 的形式。

      确实,如果您的类 A 有一个成员 B,则 const 形式是不可能的,因此隐式声明的复制构造函数采用非常量形式。

      请注意,模板化构造函数永远不是 复制 构造函数。

      【讨论】:

        猜你喜欢
        • 2016-09-12
        • 2023-03-09
        • 1970-01-01
        • 2011-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-22
        • 1970-01-01
        相关资源
        最近更新 更多