Constructor Construction operation semantics --Copy Constructor

 
In the three cases, it will be the content of an object of another class object as the initial value of:

  1. object explicitly initialized

    1
    2
    3
    class {...};
    X x;
    X xx = x;
  2. object is treated as a function and parameter post

    1
    2
    3
    4
    5
    extern void foo(X x);
    void bar(){
    X xx;
    foo(xx);
    }
  3. Function return value is a class object

    1
    2
    3
    4
    5
    X foo_bar(){
    X xx;
    ...
    return xx;
    }

If the developer has clearly defined a copy constructor as follows:

1
2
3
// copy constructor may be a multi-parameter, which is a parameter whose type class
X-X-:: ( const X-X &);
the Y :: the Y ( const the Y & Y);

So in most cases, when the class object to another similar entity as the initial value, the above-described constructor is called, which may lead to a temporary class object generation or program code changed (or both).


Default Memberwise Initialization

 
If the function does not provide an explicit copy constructor, then the copy operation is the same type of objects is done by default memberwise initialization, which performs policy: a built-in value for each data member of or derived, from one copy to another object object. But it will not be copied wherein the member class object, but the implementation of recursive memberwise initialization (default memberwise initialization are sequentially performed for each object).

Examples

Consider the following class declaration:

1
2
3
4
5
6
7
class String{
public:
...//不存在explicit copy constructor
private:
char *str;
int len;
};

String object's default memberwise initialization occurred in this case:

1
2
String noun("book");
String verb = noun;

Are sequentially performed for respective manner similar set each member:

1
2
verb.str = noun.str; 
verb.len = noun.len;

If String is another class of member:

1
2
3
4
5
6
7
class Word{
public:
...//不存在explicit copy constructor
private:
int _occurs;
String _word;
};

So a Word object's default memberwise initialization will copy its built-in member _occurs, and then perform recursive memberwise initialization of the String member.

If developers do not specify a copy constructor for the class, then the compiler will generate the definition implicit declaration of. Similar to the Default constructor, C ++ also the copy constructor is divided into two kinds of trivial and non-trivial, only non-trivial entities will be synthesized into the program in. Determine whether a copy constructor for the class is trivial basis whether to show the so-called "bitwise copy semantics".


Bitwise Copy Semantics

1
2
3
4
5
6
7


Word noun("book");

void foo(){
Word verb = noun;
}

Obviously verb is based on the noun to initialize, but before the statement did not understand the Word class, we can not predict the behavior of the program initialization operations. If the developer defines the copy constructor, then the compiler will call it. If not, it will show whether the class according to a bitwise copy semantics, to synthesize a copy constructor.

For example, if the internal data containing only Word built-in type, then the compiler will not synthesized copy constructor, but performs bitwise copy. But if the Word contains a String object, and the String class there is an explicit copy constructor, the compiler will have to synthesize a copy constructor, to call the copy constructor member object, the copy constructor in this synthesis, the built-in type still use bitwise copy.


Bitwise Copy situation does not appear

 
There are four cases a class does not show bitwise copy:

  1. class contains a member object, and the latter has a copy constructor (either specified by the developer or compiler synthesis)
  2. class inherits from a base class, while the latter there is a copy constructor (either specified by the developer or compiler synthesis)
  3. class declares one or more virtual functions
  4. The existence of class inheritance system memory in one or more virtual base class

The first two cases, the compiler will base class or member is inserted into the copy constructors synthesized in copy constructors.


Heavy set vptr

 
On the one we have expounded, class contains virtual functions will constructor spontaneous expansion during compilation:

  1. class will add a vtbl
  2. class object will add a vptr

Obviously, vptr is a key determinant of polymorphism will run correctly when the compiler vptr to import into the class, the class no longer have bitwise semantics. The compiler needs to synthesize a copy constructor, initialize the vptr reasonable.

Examples

Existing inheritance hierarchy and class the following statement:
image_1cchrq8qc1m3sqpgqhe15te9389.png-6.9kB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ZooAnimal{
public:
ZooAnimal();
virtual ~ZooAnimal();
virtual void animate();
virtual void draw();
private:
...//some data
};
class Bear : public ZooAnimal{
public:
Bear();
void animate();
void draw();
private:
...//some data
};

ZooAnimal object相互赋值或者Bear object相互赋值都可以通过bitwise copy semantics完成。在这种情况下,vptr保持bitwise copy是安全的。

当一个base class object以其derived class object内容作初始化操作时,其vptr也需要保证安全:

1
2
Bear B;
ZooAnimal Z = B;//sliced

显然,Z的vptr不应该指向Bear的vtbl,也就是说,Base class被合成出来的copy constructor会明确设定object的vptr指向Base Class的vtbl,而非从rhs处执行bitwise copy。


处理Virtual Base Class Subobject

 
一个class object如果以另一个object作为初值,而后者带有一个virtual base class subobject,那么bitwise semantics同样会失效。

在上一节中我们已经编译器需要保证在运行期明确virtual base class subobject的位置。Bitwise copy可能会破坏这个位置。

实例

现有继承体系及class声明如下:
image_1cchsh99imb2u671bk629s13ubm.png-13.9kB
···C++
class Raccoon:public virtual ZooAnimal{
public:
Raccoon();
Raccoon(int val);

private:
…//some data
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在开发者撰写的constructor中,编译器会生成:
1. 调用ZooAnimal的default constructor代码
2. Raccoon的vptr初始化代码
3. 定位Raccoon中ZooAnimal subobject代码

编译器会将上述代码插入至两个constructor之内,并且放在开头位置。

当一个class object以其derived class object作为初值时,bitwise失效,因为此时编译器必须判断“后续当程序员试图存取其Base class subobject时程序能否正常运行。
考虑如下继承体系与声明:
![image_1cchtdv2o1tvlga1o4414a752613.png-20.9kB][3]
```C++
class RedPanda:public Raccoon{
public:
RedPanda();
RedPanda(int val);
private:
...
}

Analysis existing object is as follows:
image_1cchtl7dq17ulenn30r19ej1tft20.png-130.2kB
In the following code, the compiler can not determine whether the valid bitwise copy, because the compiler can not know whether Raccoon Raccoon points to a real objects:

1
2
* Ptr Raccoon; 
Raccoon little_critter = * ptr; // ptr may point to a derived class


to sum up

 
Can we believe that in the bitwise copy entirely reasonable in the circumstances, should be prohibited in order to optimize the program calls the copy constructor? This issue will be discussed in the following sections.
In this section we discuss the class is no longer held four cases bitewise copy semantics. In these four cases, if not declared copy constructor, then the compiler in order to ensure proper initialization, will synthesize a copy constructor.

Original: Big Box  constructor semantics --Copy Constructor construction operations


Guess you like

Origin www.cnblogs.com/wangziqiang123/p/11618218.html