230 likes | 504 Views
C++ 程序语言设计. Chapter 10: the Copy-Constructor. Outline. Passing & returning by value Problem with the Bitcopy Copy-construction Default copy-constructor Pointers to members. Passing & returning by value. types built into the compiler int f(int x, char c); int g = f(a, b);
E N D
C++程序语言设计 Chapter 10: the Copy-Constructor
Outline • Passing & returning by value • Problem with the Bitcopy • Copy-construction • Default copy-constructor • Pointers to members
Passing & returning by value • types built into the compiler int f(int x, char c); int g = f(a, b); • user-defined types struct Big {char buf[100]; int i; long d;} B, B2; Big bigfun(Big b) { b.i = 100; // Do something to the argument return b; } int main() { B2 = bigfun(B); }
Problem with the Bitcopy • For passing and returning large simple structures, there is a way to copy the bits from one place to another. int a = 3; int b; b = a; • in C++ objects can be much more sophisticated than a patch of bits.
Problem with the Bitcopy See the file: HowMany.cpp class A{ public:A(){name = NULL;age = 20;} void Init(int size, int age){name = new char[size];this.age = age;} int getAge(){return age;} Private:char *name; int age; //类的对象中包含指针成员,指向动态分配内存资源 (即指向堆中分配的一内存空间) }; /*生成一个对象: A objA;objA.Init(20, 45);A objB = objA; //这时用objA初始化objB, 即必须把objA内的数据成员值赋给objB的数据成员 //即 objB.name <= objA.name;objB.age <= objA.age; 由于直接objB.name = objA.name;所以这时objB.name和objA.name同时指一个堆内存区域,从而产生了对象的内存不独立的情况 */
Copy-construction • the compiler makes an assumption about how to create a new object from an existing object HowMany h2 = f(h); • the copy-constructor --- X(X&) • this function is a constructor • the single argument to this constructor has to the object be constructing from • the reference of the source object
Copy-construction • If you create a copy-constructor, the compiler will not perform a bitcopy when creating a new object from an existing one. It will always call your copy-constructor. See the file: HowMany2.cpp
Temporary objects • It turns out the compiler can create a temporary object whenever it needs one to properly evaluate an expression. • The lifetime of this temporary object is as short as possible • the temporary might immediately be passed to another function • the function call ends the temporary object is destroyed
Default copy-constructor • if you don’t make a copy-constructor, the C++ compiler will still automatically create one, a bitcopy. • In the case of simple structures – effectively • For more complex types , a bitcopy doesn’t make sense See the file: DefaultCopyConstructor.cpp
深拷贝和浅拷贝 • 既然系统会自动提供一个默认的拷贝构造函数来处理复制,那么还有没有意义要去自定义拷贝构造函数? • 深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源,当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源但复制过程并未复制资源的情况视为浅拷贝。 • 浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错,这点尤其需要注意!
深拷贝和浅拷贝 See the file: Person.cpp • It’s always best to create your own copy-constructor instead of letting the compiler do it for you.
Preventing pass-by-value • declare a private copy-constructor • You don’t even need to create a definition, unless one of your member functions or a friend function needs to perform a pass-by-value • If the user tries to pass or return the object by value, the compiler will produce an error message. See the file : NoCopyConstruction.cpp
总结 • 当类中包含动态分配成员,用于将已有对象初始化另一个对象的情况下应提供拷贝构造函数 • COPY构造函数只有在对象声明和用另一个对象初始化它同时发生时才调用 • ClassName objA= objB; • A objA, objB;ObjB=ObjA; • 当对象直接作为参数传给函数时,函数将建立对象的临时拷贝,这个拷贝过程也将调同拷贝构造函数 • 当函数中的局部对象被被返回给函数调者时,也将建立此局部对象的一个临时拷贝,拷贝构造函数也将被调用
Pointers to members • A pointer is a variable that holds the address of some location • You can change what a pointer selects at runtime • The C++ pointer-to-member selects is a location inside a class
Pointers to members • there is no “address” inside a class • selecting a member of a class means offsetting into that class • produce an actual address by combining that offset with the starting address of a particular object
The syntax of pointers to data members • you select an object at the same time you’re dereferencing the pointer to member. struct Simple { int a; }; int main() { Simple so, *sp = &so; sp->a; so.a; } int* ip; *ip = 4; objectPointer->*pointerToMember = 47; object.*pointerToMember = 47;
The syntax of pointers to data members • int ObjectClass::*pointerToMember; • Like any pointer, you have to say what type it’s pointing at, and you use a * in the definition. The only difference is that you must say what class of objects this pointer-to-member is used with. this is accomplished with the name of the class and the scope resolution operator. • defines a pointer-to-member variable called pointerToMember that points to any int inside ObjectClass.
The syntax of pointers to data members • You can also initialize the pointer-to-member when you define it (or at any other time) . int ObjectClass::*pointerToMember = &ObjectClass::a; • &ObjectClass::a can be used only as pointer-to-member syntax see the file: PointerToMemberData.cpp
A pointer to a function • Once a function is compiled and loaded into the computer to be executed, it occupies a chunk of memory • You can use function addresses with pointers just as you can use variable addresses void (*funcPtr)(); void *funcPtr();
Using a function pointer • Just as the address of an array, the address of a function func() is produced by the function name without the argument list (func). void func() { cout << "func() called..." << endl; } int main() { void (*fp)(); fp = func; (*fp)(); void (*fp2)() = func; (*fp2)(); }
pointers to member functions • If you have a function inside a class, you define a pointer to that member function by inserting the class name and scope resolution operator into an ordinary function pointer definition see the file: PmemFunDefinition.cpp
pointers to member functions • a pointer to member function can also be initialized when it is created, or at any other time • you can selects member functions at runtime by a pointer to member function. see the file: PointerToMemberFunction.cpp PointerToMemberFunction2.cpp
next… Operator Overloading thanks!