拷贝构造函数和赋值操作符的一些细节
从开始学C++就一直记得“如果一个类没有定义拷贝构造函数或者赋值操作符,编译器会为它生成一个拷贝构造函数和一个赋值操作符。”
这个说法其实挺含糊的。今天看书的时候看到的一个例子,就让我感到十分“出乎意料”。
#include <stdio.h>
struct X { X() { };
template<typename T> X( const T& ) { printf("templated X copy constructor.");}
template<typename T> 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<typename T> 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&类型,而其后的所有参数都有缺省值即可。
程序真正执行的时候,两个函数模板均未被调用到,所以什么输出也没有。
补充:软件开发 , C语言 ,