2.2 Copy constructor的构造操作

一、三种情况下的“一个object的内容会作为另一个object对象的初值”

1.显式赋初值

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

2. 作为函数形参

void func(X x);
void bar()
{
    X x;
    //...
    func(x);
    //...   
}

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

X foo()
{
    X x;
    //...
    return x;
}

二、Default Memberwise Initialization

该标题的意思是:默认的“为每一个member施以初始化”,那么什么时候才会出发此操作呢?首先看下面的例子:

class String 
{
public:
    // ... 没有explicit copy constructor
private:
    char* str;
    int len;        
};

一个String object 的Dafault Memberwise Initialization发生再这种情况下:

String str("hello world");
String str2 = str;

// 语意相等
str2.str = str.str;
str2.len = str.len;

请记住:

1.如果class没有提供一个explicit copy destructor,当“一个object的内容会作为另一个object对象的初值”时,其内部操作是以Dafault Memberwise Initialization的手法实现,简单粗暴的讲:把每一个内建的或派生的data member的值,从一个object 拷贝到另外一个object 身上。但是,这并不会拷贝其中的member class object,而是以递归的方式施行memberwise initialization。

2.“如果一个class未定义出copy destructor,编译器就自动为它产生出一个。”这句话不对,而应该像ARM所说:Default constructors和Copy constructors在必要的时候才由编译器产生出来。请注意,是在必要的时候。而本节使用的Dafault Memberwise Initialization手法正是不必要合成拷贝构造函数的时候.必要的时候是类没展现出Bitwise Copy Semantics的时候,而本节的String类恰恰展现出了Bitwise Copy Semantics。


三、Bitwise Copy Semantics

该标题的意思是:位逐次拷贝语意。它关系到编译器是否合成一个Copy constructor。首先看下面的这段代码:

#include "Word.h"
Word noun("book");
void foo()
{
    Word verb = noun;
    // ...
}

这里verb由noun初始化而来,但在没有看到Word的声明前,我们是不确定这个初始化操作的程序行为。如果类Word的设计者定义了一个copy constructor,那么verb的初始化会调用该拷贝构造函数;如果该class没定义explicit copy constructor,那么编译器一定会合成一个拷贝构造函数被调用。很遗憾,这是错的。这就是本节讨论Bitwise Copy Semantics的目的。

请记住
如果Word类没有展现 Bitwise Copy Semantics,那么编译器会合成一个拷贝构造函数(用以调用“由编译器合成或设计者显式声明”的member class object的拷贝构造函数);否则,将不合成。


下面来看类是如何表现出Bitwise Copy Semantics的。

// 展现了Bitwise Copy Semantics
class Word
{
public:
    Word(const char*);
    ~Word(){ delete[] str; };
private:
    int cnt;
    char* str;
};

// 未展现Bitwise Copy Semantics
class Word
{
public:
    Word(const String&);
    ~Word();
private:
    int cnt;
    String str;
};

其中String 声明了一个explicit copy constructor:

class String
{
public:
    String(const char*);
    String(const String&);// 声明了显式的拷贝构造函数
    ~String();
    // ...
};

在未展现Bitwise Copy Semantics的情况下,编译器必须合成出一个copy constructor,以便调用member class String object的copy constructor:

// 一个被合成出来的copy constructor
// C++伪码
inline Word::Word(const Word& word)
{
    str.String::String(word.str);
    cnt = word.cnt;
}

什么时候不展现出Bitwise Copy Semantics呢?有以下四种情况

1.当class内含一个member class object而后者的class声明了一个copy constructor(不论是编译器合成或设计者显式声明)时。
2.当class继承自一个base class而后者存在一个copy constructor时(再次强调:不论是编译器合成或设计者显式声明)。以上两种情况下,编译器必须将member或base class 的拷贝构造函数调用操作案查倒被合成的copy constructor中。
3.当class 声明了一个或多个virtual funcitons时。
4.当class派生自一个继承串链,其中有一个或多个virtual base classes时。
下面两种情况比较复杂,接下来讨论。


参考文献:《深度探索C++对象模型》侯捷 译

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值