竞争éšå¼å’Œæ¨¡æ¿å¤åˆ¶æž„造函数

时间:2012-12-17 12:00:00

标签: c++ templates constructor copy implicit

关于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时输出å˜åŒ–;没有注释。

显然,当A(A const&)å–消注释时,éšå¼å¤åˆ¶æž„造函数会从A(A &)更改为B b;。为什么?当我将B(B&){}更改为B(const B&){}时,å¤åˆ¶æž„造函数会更改回A(A const&)。现在编译器满æ„A()çš„å½¢å¼å‚数将是const?这与标准有什么关系å—? (我正在使用gcc 4.2.4。)

2 个答案:

答案 0 :(得分:4)

ç±»Açš„éšå¼å¤åˆ¶æž„造函数的签å仅为A(const A&) ,如果å¯è¡Œã€‚å–消注释B b;行时,此å¤åˆ¶æž„造函数ä¸å¯è¡Œï¼Œå› ä¸ºBçš„å¤åˆ¶æž„造函数需è¦éžconst输入å‚数。

// 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)
{
}

在这ç§æƒ…况下,éšå¼å¤åˆ¶æž„造函数也是éžconst版本:A(A&);。

// 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将没有éšå¼å‰¯æœ¬æž„造

答案 1 :(得分:3)

是的,这个行为是由标准定义的,在12.8 / 8:

  

ç±»Xçš„éšå¼å£°æ˜Žçš„å¤åˆ¶æž„造函数将具有X::X(const X &)å½¢å¼ï¼Œå¦‚æžœ[...æ¡ä»¶æœ‰æ„义......],å¦åˆ™[它]将具有X::X(X &)å½¢å¼{ {1}}。

实际上,如果你的类A有一个æˆå‘˜B,则const表å•æ˜¯ä¸å¯èƒ½çš„,因此éšå¼å£°æ˜Žçš„å¤åˆ¶æž„造函数采用éžconstå½¢å¼ã€‚

请注æ„,模æ¿åŒ–构造函数永远ä¸æ˜¯ copy 构造函数。