Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 18: Copying the Copy Copy Copy Constructor 249

Student fn1(); int fn2(Student&);

int main(int argcs, char* pArgs[])

{

int x;

//create a Student object by calling fn1().

//Pass that object to the function fn2().

//fn2() returns an integer that is used in some

//silly calculation.

//All this time the temporary returned from fn1()

//remains valid.

x = 3 * fn2(fn1()) + 10;

//the temporary returned from fn1() is now no longer valid

//...other stuff...

return 0;

}

This makes the reference example invalid because the object may go away before refS does, leaving refS referring to a non-object.

Avoiding temporaries, permanently

It may have occurred to you that all this copying of objects hither and yon can be a bit time-consuming. What if you don’t want to make copies of every­ thing? The most straightforward solution is to pass objects to functions and return objects from functions by reference. Doing so avoids the majority of temporaries.

But what if you’re still not convinced that C++ isn’t out there craftily con­ structing temporaries that you know nothing about? Or what if your class allocates unique assets that you don’t want copied? What do you do then?

You can add an output statement to your copy constructor. The presence of this message when you execute the program warns you that a copy has just been made.

A more crafty approach is to declare the copy constructor protected, as follows:

class Student

{

protected:

Student(Student&s){}

public:

// ...everything else normal...

};

250 Part III: Introduction to Classes

This precludes any external functions, including C++, from constructing a copy of your Student objects. (This does not affect the capability of member functions to create copies.) If no one can invoke the copy constructor, no copies are being generated. Voilà.

Referring to the copy constructor’s referential argument

The fact that the copy constructor is used to create temporaries and copies on the stack answers one pesky detail that may have occurred to you. Consider the following program:

class Student

{

public: Student(Student s)

{

// ...whatever...

}

};

void fn(Student fs) {}

void fn()

{

Student ms; fn(ms);

}

Notice how the argument to the copy constructor is no longer referential. In fact, such a declaration isn’t even legal. The Dev-C++ compiler generates a hor­ rible list of meaningless error messages in this case. Another public domain C++ compiler generates the following, much more meaningful error message:

Error: invalid constructor; you probably meant ‘Student

(const Student&)’

Why must the argument to the copy constructor be referential? Consider the program carefully: When main() calls the function fn(), the C++ compiler uses the copy constructor to create a copy of the Student object on the stack.

However, the copy constructor itself requires an object of class Student. No problem, the compiler can invoke the copy constructor to create a Student object for the copy constructor. But, of course, that requires another call

to the copy constructor, and so it goes until eventually the compiler collapses in a confused heap of exhaustion.