从开始学C++就一直记得“如果一个类没有定义拷贝构造函数或者赋值操作符,编译器会为它生成一个拷贝构造函数和一个赋值操作符。”
这个说法其实挺含糊的。今天看书的时候看到的一个例子,就让我感到十分“出乎意料”。
#include
struct X
{
X() { };
template
X( const T& ) {
printf("templated X copy constructor.");
}
template
X& operator=( const T& ) {
printf("templated X assignment operator.");
}
};
int
main(int argc, char** argv) {
X x1;
X x2(x1);
X x3;
x3 = x1;
}
这个程序编译后,执行结果是啥?答案:啥也没有!两个函数模板都没有被调用到。
原因说起来并不十分复杂,但能看出,我对C++的细节还是不够清楚。好,现在细节来了:
C++标准(ISO/IEC 14882:2003(E))12.8.2写的清楚:
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6).
要点:带有模板参数的函数模板,不算是构造函数。
所以上面例子中声明的template X(const T&)这个函数不是拷贝构造函数。
并且按照这段话对拷贝构造函数的定义,上面的类定义里没有显式地定义任何拷贝构造函数。
C++标准接着说:If the class definition does not explicitly declare a copy constructor, one is declared implicitly.
这个是学过C++的人基本都知道的事情。所以编译器要为上面的类生成一个隐式的拷贝构造函数。
编译器生成的隐式拷贝构造函数,所做的事情就是对类的所有成员一一做浅拷贝,自然没有任何输出。
赋值操作符的情形类似。标准定义为:
A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&.
即:赋值操作符必须是一个非模板的、非静态的成员函数,而且只能有一个参数。这一点和拷贝构造函数还不同。拷贝构造函数可以有多个参数,只要第一个是X&或者cv-qualified X&类型,而其后的所有参数都有缺省值即可。
程序真正执行的时候,两个函数模板均未被调用到,所以什么输出也没有。
阅读(573) | 评论(0) | 转发(0) |