C++构造函数语意学——默认拷贝构造函数

来源:互联网 发布:广州君海网络热血霸业 编辑:程序博客网 时间:2024/05/09 01:01

概述

使用 class object 时,在以下三种情况会以一个 object 的内容作为另一个 class object 的初值,即用到拷贝构造函数:

  1. 定义一个 class object 并对其进行初始化;
  2. class object 作为一个参数传递给函数;
  3. class object 作为函数的返回值;

若用户没有显示声明或定义拷贝构造函数,则 C++ 在 必要 时为 class 声明或定义隐式拷贝构造函数,若出现以下的情况时,该拷贝构造函数是 trivial 的:

  1. their class has no virtual functions and no virtual base class(es).
  2. all direct base classes and non-static data members of their class have trivial constructors.
  3. Otherwise, the copy constructor are non-trivial. Implicitly-declared non-trivial copy constructor.

默认拷贝构造函数

在以下四种情况下,编译器会合成一个 non-trivial 的默认拷贝构造函数:

  1. 当 class 内含一个具有 copy constructor 的 member object;
  2. 当 class 继承自一个具有 copy constructor 的 base class;
  3. 当 class 声明有 virtual functions;
  4. 当 class 派生自 virtual base class(es);

前面两种情况,编译器必须将 member 或 base class 的 copy constructor 放置在默认拷贝构造函数中,以下例子同时满足这两个情况:

#include <iostream>using namespace std;class Foo {public:    Foo() {}    Foo(const Foo &foo) { cout << "Foo's copy construct!" << endl; }};class Word: public Foo {public:    int x;    Foo foo;};int main(){    Word ba;    Word bb = ba;    return 0;}

执行结果:编译器在合成的拷贝构造函数中调用了两次 Foo 类的拷贝构造函数;

(gdb) rStarting program: ./test02 Breakpoint 1, main () at test02.cpp:2020      Word ba;(gdb) sWord::Word (this=0xbffff020) at test02.cpp:1111  class Word: public Foo {(gdb) sFoo::Foo (this=0xbffff020) at test02.cpp:77       Foo() {}(gdb) sFoo::Foo (this=0xbffff024) at test02.cpp:77       Foo() {}(gdb) smain () at test02.cpp:2121      Word bb = ba;(gdb) sWord::Word (this=0xbffff028) at test02.cpp:1111  class Word: public Foo {(gdb) sFoo::Foo (this=0xbffff028, foo=...) at test02.cpp:88       Foo(const Foo &foo) { cout << "Foo's copy construct!" << endl; }(gdb) sFoo's copy construct!Foo::Foo (this=0xbffff02c, foo=...) at test02.cpp:88       Foo(const Foo &foo) { cout << "Foo's copy construct!" << endl; }(gdb) sFoo's copy construct!main () at test02.cpp:2222      return 0;(gdb) s23  }(gdb) 

第三种情况,若是相同 class 的 object 直接的初始化,可以采用 bitwise copy 方式进行,因为 vptr 指向相同的虚函数表;若是使用派生类 object 初始化 基类 object 时,则编译器会重新设定 class object 的 virtual table 的指针,因为不同类的 vptr 指向各自的虚函数表;

#include <iostream>using namespace std;class Foo {public:    virtual void func()    { cout << "virtual function in Foo!" << endl; }};class Word: public Foo {public:    void func()    { cout << "virtual function in Word!" << endl; }};int main(){    Word b1;    Word b2 = b1;    // 相同类对象之间初始化,vptr直接复制,指向相同的virtual function table    b2.func();    Foo foo = b1;   // 不同类对象之间初始化,发生切割,vptr不直接复制,指向不同的virtual function table    foo.func();    return 0;}

执行结果:

(gdb) b 19Breakpoint 1 at 0x8048809: file test03.cpp, line 19.(gdb) rStarting program: /home/nifengweijifen/linuxStudy/ObjectModel/chap02/test03 Breakpoint 1, main () at test03.cpp:1919      Word b1;(gdb) sWord::Word (this=0xbffff024) at test03.cpp:1212  class Word: public Foo {(gdb) sFoo::Foo (this=0xbffff024) at test03.cpp:66   class Foo {(gdb) smain () at test03.cpp:2020      Word b2 = b1;    //相同类之间的初始化,直接复制 vptr,指向相同的virtual function table(gdb) sWord::Word (this=0xbffff028) at test03.cpp:1212  class Word: public Foo {(gdb) sFoo::Foo (this=0xbffff028) at test03.cpp:66   class Foo {(gdb) smain () at test03.cpp:2121      b2.func();(gdb) sWord::func (this=0xbffff028) at test03.cpp:1515      { cout << "virtual function in Bar!" << endl; }(gdb) svirtual function in Word!main () at test03.cpp:2323      Foo foo = b1;   // 不同类之间的初始化,发生切割,vptr不直接复制,指向不同的virtual function table(gdb) sFoo::Foo (this=0xbffff02c) at test03.cpp:66   class Foo {(gdb) smain () at test03.cpp:2424      foo.func();(gdb) sFoo::func (this=0xbffff02c) at test03.cpp:99       { cout << "virtual function in Foo!" << endl; }(gdb) svirtual function in Foo!main () at test03.cpp:2525      return 0;(gdb) s26  }(gdb) 

第四种情况和第三种情况相似,若是相同 class 的 object 直接的初始化,可以采用 bitwise copy 方式进行;若是使用派生类 object 初始化 基类 object 时,则编译器会重新设定 virtual base class 的指针;

1 0
原创粉丝点击