说到拷贝构造函数(copy constructor),使用c++的人都不陌生。概念这里不再重述,它的调用发生在当声明一个对象时用另外一个对象对这个对象进行初始化操作的时候。这句话表述的很拗口,但是条件缺一不可。
顾名思义,拷贝构造函数。首先应该是一个构造函数,所谓构造函数,是指用来构造一个对象的函数,所以只有在构造对象的时候才会调用(听起来好像是一句废话)。来看下面的例子:
点击(此处)折叠或打开
-
class A{
-
};
-
-
A a;//发生了构造行为调用构造函数
-
A aa;//发生了构造行为调用构造函数
-
-
A aaa = a;//发生了构造行为,一般情况下会调用拷贝构造函数
- A aa = a;//未发生构造行为,调用重载的“=”运算符
另外的两类情形,一般情况下回调用拷贝构造函数:
点击(此处)折叠或打开
-
void test(A a);//当对象最为一个函数的形参的时候
- A test();//当对象作为一个函数的返回值的时候
具体来解释一下就是,当发生对象拷贝的时候,如果该对象内部并没有声明一个拷贝构造函数,一个良好的编译器可以对大部分的对象进行bitwise copies。简单来说将是讲一个对象内存空间的内容按位拷贝到另外一个对象的内存空间之中,而不会调用拷贝构造函数。
举个例子来说明下:
点击(此处)折叠或打开
-
class A
-
{
-
public:
-
A(const char* s)
-
{
-
name = new char[strlen(s) + 1];
-
strcpy(name, s);
-
age = 10;
-
}
-
~A()
-
{
-
delete name;
-
}
-
char * name;
-
int age;
-
};
-
-
int main()
-
{
-
-
A a("ddx");
-
A b = a;
-
cout << a.name << endl;
-
cout << b.name << endl;
-
cout << sizeof(a) << endl;
-
cout << "a和b的内存位置" << endl;
-
cout << (unsigned long)&a << endl;
-
cout << (unsigned long)&b << endl;
-
cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"<<endl;
-
-
cout << "a的内存布局" << endl;
-
cout << (unsigned long)(a.name) << endl;//3413920
-
cout << (unsigned long)&(a.name) << endl;
-
cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"<<endl;
-
-
cout << "b的内存布局" << endl;
-
cout << (unsigned long)(b.name) << endl;//3413920
-
cout << (unsigned long)&(b.name) << endl;
-
return 0;
- }
c++面向对象模型之中又如何表述,当存在下列情况时类不符合bitwise copy semantics。
1、当类含有对象类型的成员变量,而该成员变量的类声明中含有拷贝构造函数的时候(该拷贝构造函数包括编译器自动生成的)。
2、当该类的父类存在拷贝构造函数的时候。
3、该类声明了一个或者多个虚函数。
4、该类派生自一个继承串链,其中存在虚基类的情况。
除了上述的四种情况,其他的类如果未声明拷贝构造函数的情况下,将不生成默认的拷贝构造函数,而直接进行bitwise copy。
参考:深度探索c++对象模型