Question:
When a Copy Constructor is not written for a class, the C++ compiler generates one. Which of the following statements correctly describe the actions of this compiler-generated Copy Constructor when invoked? (当类中没有拷贝构造函数时,编译器会自己生成1个,下列说法正确的是:)
A. The compiler-generated Copy Constructor makes the object being constructed, a reference to the object passed to it as an argument. (编译器生成的拷贝构造函数使对象被构造,对象的引用作为一个参数)
B. The compiler-generated Copy Constructor does not do anything by default. (编译器生成的拷贝构造函数默认情况什么都不做)
C. The compiler-generated Copy Constructor performs a member-wise copy of the object passed to it as an argument, into the object being constructed. (编译器生成的拷贝构造函数执行,一个对象的成员拷贝作为一个参数,传入对象被构造)
D. The compiler-generated Copy Constructor tags the object as having been Copy-Constructed by the compiler. (编译器生成的拷贝构造函数给对象贴标签作为被“拷贝构造”了)
E. The compiler-generated Copy Constructor invokes the assignment operator of the class. (编译器生成的拷贝构造函数调用类的运算符)
Analysis:
A compiler-generated default constructor sets up the object (initializes vftables and vbtables, as described previously), and it calls the default constructors for base classes and members, but it takes no other action.
A compiler-generated copy constructor sets up a new object and performs a memberwise copy of the contents of the object to be copied. If base class or member constructors exist, they are called; otherwise, bitwise copying is performed.
If all base and member classes of a class type have copy constructors that accept a const argument, the compiler-generated copy constructor accepts a single argument of type const type&. Otherwise, the compiler-generated copy constructor accepts a single argument of type type&.
Answer: AC
Shallow Copy: Shallow copy is bit-wise copy. A shallow copy copies each member of the class individually using the assignment operator.
Deep Copy: Deep copy is member-wise copy. A deep copy duplicates the object or variable being pointed to so that the destination receives local copy of its own.
Shallow Copy = Bitwise Copy,Deep Copy = Memberwise Copy.
Long story short, a shallow copy only copies the binary, in memory, print of a class. A deep copy “dives into” the members, and copy their logical data. Usually, by default, it is a Shallow/Bitwise copy.
Example: If you've got a class with one member, which is a pointer of irrelevant type, a shallow copy would duplicate the address, leaving you with two classes with pointers to the same value. A deep copy would copy what the pointer addresses, again giving you two classes, but each with a pointer to its own value. Not only will the class be copied, but also whatever types it contains.
下面是Shallow/Bitwise Copy的图解:
对象(地址0x200000B0)被浅拷贝到另外一个对象(地址0x200000C0),由于其中含有一个字符串对象,其地址为0x200000D0,在浅拷贝的时候,只是简单地将地址拷贝到新对象,因此原对象和新对象所指向的内容是一样的,都是“Hello, World”,如果新对象将该字符串进行了修改,那么原对象中对应的字符串也会发生同样的变化。而这在大部分情况下是不能接受的。
Just to be pedantic the compiler actually doesn't generate code that copies the object one bit at a time - it is at least one byte at a time. But the underlying meaning is the same: the way I think of it is a shallow/bitwise copy can be done using memcpy while a deep/member wise copy requires calling copy constructor/assignment operators for user-defined types. Note: for built in types, like int, char, etc., there is only one way to copy the object and that is a bitwise copy.
Here is a pieace of code I wrote to demo the shallow & deep copy:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Learning
{
[Serializable]
class Test1
{
public int i;
}
[Serializable]
class cloneTest
{
public int j;
public Test1 t = new Test1();
public object ShallowCopy()
{
return this.MemberwiseClone();
}
public object Clone()
{
BinaryFormatter BF = new BinaryFormatter();
MemoryStream memStream = new MemoryStream();
BF.Serialize(memStream, this);
memStream.Flush();
memStream.Position = 0;
return (cloneTest)BF.Deserialize(memStream);
}
}
class ClassMain
{
public static void DemoDeepCopy()
{
Console.WriteLine("Demoing Deep Copy");
cloneTest ct = new cloneTest();
ct.j = 1;
ct.t.i = 2;
cloneTest ct2 = (cloneTest) ct.Clone();
/*Even we can do shallo copy directly here
* BinaryFormatter BF = new BinaryFormatter();
MemoryStream memStream = new MemoryStream();
BF.Serialize(memStream, ct);
memStream.Flush();
memStream.Position = 0;
cloneTest ct2 = (cloneTest)BF.Deserialize(memStream);*/
ct2.j = 31;
ct2.t.i = 41;
Console.WriteLine("ct.j = " + ct.j + "; ct.t.i = " + ct.t.i);
Console.WriteLine("ct2.j = " + ct2.j + "; ct2.t.i = " + ct2.t.i);
}
public static void DemoShalloCopy()
{
Console.WriteLine("Demoing of Shallow Copy");
cloneTest ct = new cloneTest();
ct.j = 1;
ct.t.i = 2;
cloneTest ct2 = (cloneTest)ct.ShallowCopy();
ct2.j = 3;
ct2.t.i = 4;
Console.WriteLine("ct.j = " + ct.j + "; ct.t.i = " + ct.t.i);
Console.WriteLine("ct2.j = " + ct2.j + "; ct2.t.i = " + ct2.t.i);
}
public static void Main()
{
DemoDeepCopy();
DemoShalloCopy();
}
}
}
I hope this clarifies the difference.
see: http://social.msdn.microsoft.com/Forums/zh-HK/vclanguage/thread/c9289b1c-c3ff-4498-a14d-4136693af7ac
转载请注明出处, 作者联系方式:hongszh at gmail.com
在看《深度探索C++对象模型》的时候,碰到了Memberwise和bitwise的说法,仔细推敲了一下memberwise就是C++中成员初始化的一个泛称,而bitwise是初始化过程中的一个特殊情况,这里按我的理解对memberwise和bitwise做一个文字总结,不对的地方欢迎对该话题感兴趣的朋友提出好的见解。
Memberwise Initialization
在P49,Default Memberwise Initialization一节:如果一个class没有提供一个explicit copy construct,当该class object以相同class的另一个object作为初值时,其内部就是以所谓的memberwise initialization手法完成的。也就是把每一个内建的或派生的data member(比如一个指针或一数组)的值,从某一个object拷贝一份到另一个object身上,不过它并不会拷贝其中的member class object(这里所说的这种情况应该是member class也不包含copy constructor,不论是被class设计者明确声明,或者是被编译器合成),而是以递归的方式施行memberwise initialization。
所以这里的memberwise initialization 就是bitwise copy。
那么如果一个class没有提供一个explicit copy construct,当该class object以相同class的另一个object作为初值时,别且有一个member class object,这个member class 有一个copy constructor(不论是被class设计者明确声明,或者是被编译器合成,总之它是nontrivial),这种情况下该class就不会展现出“bitwise copy semantics”,就是说不会以递归的方式对member class object施行memberwise initialization,而是通过调用member class的copy constructor完成memberwise initialization。
Bitwise copy
综上所述,bitwise copy前提条件是class没有提供一个explicit copy construct,可以分两个方面去理解:一个是含有member class oject的情况,一个是继承自一个base class的情况;当然对于class中含有virtual functions或者含有virtual base classes的情况就不用讨论了,肯定不会出现bitwise copy。
1. 如果一个class没有提供一个explicit copy construct,当该class object以相同class的另一个object作为初值时,如果它有一个member class object,初始化member class object的时候是以递归的方式进行memberwise initialization,不会调用copy constructor进行初始化。
2. 如果一个class没有提供一个explicit copy construct,当该class object以相同class的另一个object作为初值时,如果它继承自一个base class,该base class不存在一个copy constructor(没有被class设计者明确的声明,也不会被编译器合成),初始化base class的部分类似初始化member class object,直接copy base class相关member给要被初始化的base class的相关member。
Memberwise Assignment & Memberwise Initialization
一个class object可以从两种方式获得,一种是被初始化(initialization),一种是赋值(assignment),排除bitwise copy的情况,它们之间的主要区别是memberwise assignment调用每一个成员assignment operator(operator=),而memberwise initialization调用每一个成员的copy constructor。
see: http://hi.baidu.com/hongszh/blog/item/c312c4ca63c2584ef21fe797.html