12.3 Things to remember when using the new in constructors
If you use the new in constructors, use the delete in destructor. Their use should is compatible, pair new with delete and new [] with delete []
) Multiple constructors should share the same by new--whether all [] or all without [] (for there are only one Destru ctor
) Define a copy constructor that initializes an object to another by doing deep copy
) Define an assignment operator , copies one object to another by doing deep copy(check for Self-ass Ignment, free previous memory, deep copy, return reference to invoking object)
Suppose you has code like this, which uses the string class and the standard string class:
class Magazine{private: String title; string publisher;...};
Does need a copy constructor and a assignment operator for the Magazine class? No, because the default copy constructor would do memberwise copy, which uses the copy constructor of class String and string separately, so it's indeed a deep copy.
If the class involves pre-defined class objects and other members which need deep copy, you might has to access the copy Constructor in string and string class explicitly
12.4 Observations about returning objects
) Returning a reference to a const object
const Vector & Max(const Vector & v1, const Vector & v2){ if (v1.magval() > v2.magval()) return v1; else return v2;}
First, returning an object invokes the copy constructor and while returning a reference don ' t. So it's a bit faster.
Second, the reference should point to a object that exists during the calling function:
const int & thing(int a, int b){ int temp = a+b; return temp; // invalid! temp expired after the scope so the reference points to nothing}
Third, both V1 and V2 in the upper example are const, so the return type have to was const to match
) Returning a reference to a Non-const object
Uses: overloading the assignment operator and overloading the << operator for chained output W ITH cout
s3 = s2 = s1
In chained assignment, "s3 = S2 = S1" are same as "S3 = s2.operator= (S1)", so the assignment operator function modifies s2 and returns it, thus leaving it non-const
) return an Object
If The object being returned is a local to the called function and then return the object. overloaded arithmetic operators fall into this category.
To sum up,
| Chart |
Const |
Non-const |
| Reference |
Higher efficiency, input arguments all const |
Overloading assignment Operator/overload << operator |
| Object |
To avoid certain misuse |
Return local objects, which is defined inside methods |
12.5 Using pointers to Objects
Sample Code:
Saying2.cpp--using pointers to objects//compile with string1.cpp#include <iostream> #include <cstdlib> #i Nclude <ctime> #include "string1.h" const int arsize = 10;const int maxlen = 81;int Main () {using namespace std; String name; cout << "Hi, what ' s your name?\n>>"; CIN >> name; cout << name << ", please enter ' up ' << arsize <<" Short sayings <empty line to quit>:\n "; String Sayings[arsize]; Char Temp[maxlen]; int i; for (i = 0; i < arsize; i++) {cout << i+1 << ":"; Cin.get (temp, maxlen); while (Cin && cin.get ()! = ' \ n ') continue; if (!cin | | temp[0] = = ' + ') break; else sayings[i] = temp; } int total = i; if (Total > 0) {cout << ' here is your sayings:\n '; for (i = 0; i < total; i++) cout << sayings[i] << "\ n"; String * ShoRtest = &sayings[0]; String * first = &sayings[0]; for (i = 1; i < total; i++) {if (Sayings[i].length () < Shortest->length ()) Shor Test = &sayings[i]; if (Sayings[i] < *first) First = &sayings[i]; } cout << "Shortest saying:\n" << * shortest << Endl; cout << "First alphabetically:\n" << * First << Endl; Srand (Time (0)); int choice = rand ()% total; String * favorite = new string (Sayings[choice]); cout << "My favorite saying:\n" << *favorite << Endl; Delete favorite; } else cout << "Not much to say, eh?\n"; cout << "bye.\n"; return 0;}
Noteworthy:
1 object initialization with new:
Class_name * pclass = new Class_name(value);
which invokes constructors.
2 using pointer to object:
String * shortest = &sayings[i];
Remember that access class's member by pointer uses the "--" Opereator:
if (sayings[i].length() < shortest->length())
) destructors is called in following situations:
1 If an object was an automatic variable, the object ' s destructor was called when the program exits the block in WH Ich the object is defined
2 If an object is a static variable, it destructor is called when the program terminates
3 If an object was created by New, its destructor was only called when explicitly delete the object
12.5.2 looking again at placement new
Placenew1.cpp-New, placement new, no delete#include <iostream> #include <string> #include <new> using namespace Std;const int BUF = 512;class justtesting{private:string words; int number;public:justtesting (const string & s = "Just testing", int n = 0) {words = s; Number = n; cout << words << "constructed\n"; } ~justtesting () {cout << words << "destroyed\n"; } void Show () const {cout << words << "," << number << Endl; }};int Main () {char * buffer = new CHAR[BUF]; Justtesting *PC1, *PC2; PC1 = new (buffer) justtesting; PC2 = new Justtesting ("Heap1", 20); cout << "Memory block addresses:\n" << "Buffer:" << (void *) buffer << "heap:" << PC2 << Endl; cout << "Memory contents:\n"; cout << pc1 << ":"; Pc1->show (); cout << pc2 << ":"; Pc2-> Show (); Justtesting *PC3, *PC4; PC3 = new (buffer) justtesting ("Bad Idea", 6); PC4 = new Justtesting ("Heap2", 10); cout << "Memory contents:\n"; cout << pc3 << ":"; Pc3->show (); cout << pc4 << ":"; Pc4->show (); Delete PC2; Delete PC4; delete [] buffer; cout << "done\n"; return 0;}
The program using placement new has 2 problems:
1 Creating a second object would rewrite the first one in the buffer
Solution:
pc1 = new (buffer) JustTesting;pc3 = new (buffer + sizeof(JustTesting)) JustTesting("Better Idea", 6);
2 Freeing the buffer by "delete [] buffer" doesn "t-call the destructor of the objects containing
Solution:call the Destructors explicitly
pc3->~JustTesting();pc1->~JustTesting();
Revised Code:
Placenew1.cpp-New, placement new, no delete#include <iostream> #include <string> #include <new> using namespace Std;const int BUF = 512;class justtesting{private:string words; int number;public:justtesting (const string & s = "Just testing", int n = 0) {words = s; Number = n; cout << words << "constructed\n"; } ~justtesting () {cout << words << "destroyed\n"; } void Show () const {cout << words << "," << number << Endl; }};int Main () {char * buffer = new CHAR[BUF]; Justtesting *PC1, *PC2; PC1 = new (buffer) justtesting; PC2 = new Justtesting ("Heap1", 20); cout << "Memory block addresses:\n" << "Buffer:" << (void *) buffer << "heap:" << PC2 << Endl; cout << "Memory contents:\n"; cout << pc1 << ":"; Pc1->show (); cout << pc2 << ":"; Pc2-> Show (); Justtesting *PC3, *PC4; PC3 = new (buffer) justtesting ("Bad Idea", 6); PC4 = new Justtesting ("Heap2", 10); cout << "Memory contents:\n"; cout << pc3 << ":"; Pc3->show (); cout << pc4 << ":"; Pc4->show (); Delete PC2; Delete PC4; delete [] buffer; cout << "done\n"; return 0;}
Cpp Chapter 12:classes and Dynamic Memory Allocation Part2