设为首页 加入收藏

TOP

C++对象模型――Copy Constructor 的建构操作(第二章)(一)
2015-11-21 00:56:38 来源: 作者: 【 】 浏览:4
Tags:对象 模型 Copy Constructor 建构 操作 第二章

2.2 Copy Constructor 的建构操作

有三种情况,会以一个object的内容作为另一个 class object的初值,最明显的一种情况就是对一个object做显式的初始化操作,例如:
class X { ... };
X x;
// 明确地以一个object的内容作为另一个class object的初值
X xx = x;
另两种情况是当object被当作参数交给某个函数时,例如
extern void foo(X x);
void bar() {
    X xx;
    // 以xx作为foo()第一个参数的初值(隐式的初始化操作)
    foo(xx);
}
以及当函数传回一个 class object时。例如:
X foo_bar() {
    X xx;
    return xx;
}
假设 class 设计者明确定义了一个copy constructor(这是一个constructor,有一个参数的类型是其 class type),例如:
// user-defined copy constructor的实例
// 可以是多参数形式,其第二个参数及后继参数以一个默认值供应之
X::X(const X &x);
Y::Y(const Y &y, int = 0);
那么在大部分情况下,当一个 class object以另一个同类实体作为初值时,上述的constructor会被调用。这可能会导致一个暂时性 class object的产生或程序代码的蜕变。

Default Memberwise Initialization

如果 class 没有提供一个explicit copy constructor会怎样? 当 class object以相同class的另一个object作为初值时其内部是以所谓的default memberwise initialization完成的,也就是把每一个内建的或派生的data member(例如一个指针或数组)的值,从某个object拷贝一份到另一个object,不过它并不会拷贝其中的member class object,而是以递归的方式施行memberwise initialization。例如,考虑下面这个 class 声明:
class String {
public:
    // ... 没有 explicit copy constructor
private:
    char *str;
    int len;
};
一个String object的default memberwise initialization发生在这种情况下:
String noun(book);
String verb = noun;
    其完成方式就像个别设定每一个members一样:
verb.str = noun.str;
verb.len = noun.len;
如果一个String object被声明为另一个 class 的member,如下所示:
class Word {
public:
    // ... 没有 explicit copy constructor
private:
    int _occurs;
    String _word;    // String object成为class Word的一个member
};
那么一个Word object的default memberwise initialization会拷贝其内建的member _occurs,然后再从String member object _word递归实施memberwise initialization。
这样的操作如何实际上是怎样完成的?ARM指出:
从概念上而言,对于一个 class X,这个操作是被一个copy constructor实现出来。
关键的是概念上,这个注释紧跟着一些解释:
一个良好的编译器可以为大部分 class objects产生bitwise copies,因为它们有bitwise copy semantics...
也就是说,如果一个class未定义出copy constructor,编译器就自动为它产生出一个这句话是不对的,而是应该像ARM所说:
Default constructors和copy constructors在必要的时候采油编译器产生出来。
这个句子的必要是指 class 不展现bitwise copy semantics时。C++ Standard仍然保留了ARM的意义,但将相关讨论更形式化如下:
一个 class object可以从两种方式复制得到,一种是被初始化,另一种是被指定(assignment)。从概念上而言,这两个操作分别是以copy constructor和copy assignment operator 完成的。
就像default constructor一样,C++ Standard指出,如果 class 没有声明一个copy constructor,就会有隐式的声明出现。C++ Standard把copy constructor区分为trivial和nontrivial两种,只有nontrivial的实体才会被合成于程序中,决定一个copy constructor是否为trivial的标准在于 class 是否展现出所谓的bitwise copy semantics。

Bitwise Copy Semantics (位逐次拷贝)

在下面的程序片段中:
#include Word.h
Word noun(book);
void foo() {
    Word verb = noun;
}
很明显verb是根据noun来初始化,但在尚未看到 class Word声明之前,不可能预测这个初始化操作的程序行为,如果 class Word的设计者定义了一个copy constructor,verb的初始化操作会调用它,但如果该 class 没有定义explicit copy constructor,那么是否会有一个编译器合成的实体被调用呢?这就视该 class 是否展现bitwise copy semantics而定。如下所示:
// 以下声明展现了bit copy semantics
class Word {
public:
    Word(const char *);
    ~Word() {
        delete []str;
    }
private:
    int cnt;
    char *str;
};
这种情况下并不需要合成出一个default copy constructor,因为上述声明展现了default copy semantics,因此verb的初始化操作就不需要一个函数调用,然而,如果 class Word是这样声明的:
// 以下声明并未展现出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();
};
在这种情况下,编译器必须合成出一个copy constructor以便调用member class String ob
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇插入排序、冒泡排序、选择排序、.. 下一篇poj 1364 King(差分约束)(中等)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: