您的位置:首页 > 编程语言 > C语言/C++

C++拷贝构造函数语意学 copy constructor(The Semantics of Constructors)

2015-10-26 20:27 513 查看

使用copy constructor的三种情况

有三种情况,会以一个object的内容作为另一个class object的初值。

1.显式的以一个object的内容作为另一个class object的初值

class X{......};
X x;
X xx = x;


2.当object被当做参数交给某个函数时

void foo(X x);
void bar(){
X xx;
foo(xx);
}


3.当函数传回一个class object时

X foo(){
X xx;
return xx;
}


Explicit Copy Constructor

用户显式定义的copy consyructor大部分情况下以另一个同类实例作为初值。

如:

X::X(const X& x);
Y::Y(const Y& y,int = 0);


并注意传入参数必须是reference的

因为如果定义如下copy consyructor

X::X(X x)//ERROR: Copy constructor must pass its first argument by reference


X(X x)是传值函数。把形参复制到实参时需要调用copy constructor ,会造成无休止的递归。

Default Memberwise Initialization(默认逐位初始化)

如果class没有提供一个Explicit Copy Constructor时,当class object 以相同的class的另一个object作为初值,其内部是以Default Memberwise Initialization手法完成的,也就是把每一个内建的或派生的data member的值,从某个object拷贝一份到另一个object身上。不过并不会拷贝member class object,而是以递归的方式施行memberwise initialization.

例如:

class MyString{
public:
//没有Explicit Copy Constructor
private:
char* str;
int len;
};


发生如下操作时

MyString noun("book");
MyString verb = noun;


其方式就像如下:

verb.str = noun.str;
verb.len = noun.len;
//member class object以递归的方式施行memberwise initialization


No Bitwise Copy Semantics(不位逐次拷贝)

若一个class不展现出bitwise copy semantics时,编译器需合成copy constructor,而非简单的 bitwise copy。下面四种情况将展现 No Bitwise Copy Semantics.

1.当class内含一个声明有 copy constructor(不论是显式声明还是由编译器合成)的member object时。

如:

class X{
public:
X(X& x){
printf("X copy constructor\n");
}
};

class Y{
public:
X xx;
};


Y被合成出的copy constructor类似这样:

inline Y::Y(const Y& yy){
this.xx.X::X( yy.xx );//调用X的copy constructor传入yy的xx成员。将结果赋予this.xx
}


2.当class继承自一个存在 copy constructor 的 base class

详情同上

3.当class声明了一个或多个virtual functions时

当class声明了一个或多个virtual functions时,编译器需对每一个新产生的class object 的 vptr 进行正确的设置。

我们定义两个class如下:

class ZooAnimal{
public:
ZooAnimal() = default;
virtual void animate();
virtual void draw();
};

class Bera: public ZooAnimal{
public:
void animatr();
void draw();
virtual void dance();
};


ZooAnimal class object 以另一个ZooAnimal class object 作为初值,或Bear class object 以另一个Bear class object 作为初值,都可直接靠bitwise copy semantics 完成,因为其vprt指向同一位置。

如:

Bear yogi;
Bear winnie = yogi;//可直接靠bitwise copy semantics 完成


winnie的vprt应指向Bear class的virtual table。而yogi也是如此,所有使用逐位拷贝是安全的。



编译器也需保证一个base class object以其derive class 的 object 内容做初始化操作时vptr的复制是安全的。

Bear yogi;
ZooAnimal frannny = yogi;//此时vptr的操作应是安全的




合成出的ZooAnimal copy constructor会设定object的vptr,以指向ZooAnimal的virtual table。

4.当class派生自一个继承串联,其中有一个或多个virtual base class时

编译器需在copy constructor调用virtual base class 的default constructor ,并设置vptr 和 定位派生类中 virtual base class subobject。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++