448,650 Members | 1,772 Online
Need help? Post your question and get tips & solutions from a community of 448,650 IT Pros & Developers. It's quick & easy.

# Copy Constructor and other questions

 P: n/a I have a couple of questions. 1. Copy Constructor. class A { private: int a1; double d1; char *ptr; public: const A* operator=(const A* b) { memcpy(this, b, sizeof(A)); ptr = new char[100]; }; }; int main() { A *b = new b; A *c=b; ............. .......... }; Does C++ guarantee that my memcpy always make an exact duplicate of Object 'b' no matter how big the class is. Is this a general way of writing copy constructors? 2. Null Reference. For example we have a function that searches a list and returns a pointer to an object if it is found or NULL if it can't find the object. How can I do this if I want to return a reference instead of a pointer, without throwing exceptions? 3. This code is from FAQ lite. class Point { public: static Point rectangular(float x, float y); // Rectangular coord's static Point polar(float radius, float angle); // Polar coordinates // These static methods are the so-called "named constructors" ... private: Point(float x, float y); // Rectangular coordinates float x_, y_; }; inline Point::Point(float x, float y) : x_(x), y_(y) { } inline Point Point::rectangular(float x, float y) { return Point(x, y); } inline Point Point::polar(float radius, float angle) { return Point(radius*cos(angle), radius*sin(angle)); } int main() { Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular Point p2 = Point::polar(5.7, 1.2); // Obviously polar ... } Dumb question. Now who owns p1 and p2 and how can I delete them? Thanks for your time and help --MSR Jul 23 '05 #1
14 Replies

 P: n/a MSR wrote: class A { private: int a1; double d1; char *ptr; public: const A* operator=(const A* b) { memcpy(this, b, sizeof(A)); ptr = new char[100]; }; }; Does C++ guarantee that my memcpy always make an exact duplicate of Object 'b' no matter how big the class is. Is this a general way of writing copy constructors? Yes, memcpy makes an exact copy of the memory pointed to but... NO, NO, NOOOOOOO This is not the general way of writing copy constructors!!! Besides, what you coded is the assignment operator. Well, sort of. Usually they deal with const references to the source object, not pointers. Consider these problems: A alpha; alpha = α // hint, think memory leak Consider passing a pointer to a class derived from A??? IIRC 'this' points to *all* the storage for the object, and I believe in most implementations the first thing there is the vtbl pointer. So your blind memcpy will step on the A's vtbl pointer and point it at the derived class's vtbl. Madness surely lies down this path... I know I know, your example doesn't have virtual methods but I'm being general here. And in general, memcpy is a bad idea in C++. A more usual copy constructor for A would look something like: A( const A& src ) : a1(src.a1), d1(src.d1), ptr(NULL) { if(src.ptr != NULL) { ptr = new char[ std::strlen(src.ptr) + 1 ]; std::strcpy(ptr,src.ptr); } } And an assignment operator would look like: A& operator=( const A& src ) { if( &src != this ) // check for self-assignment { a1 = src.a1; d1 = src.d1; delete[] ptr; if( src.ptr == NULL ) ptr = NULL; else { ptr = new char[ std::strlen(src.ptr) + 1 ]; std::strcpy(ptr,src.ptr); } } return *this; } 2. Null Reference. For example we have a function that searches a list and returns a pointer to an object if it is found or NULL if it can't find the object. How can I do this if I want to return a reference instead of a pointer, without throwing exceptions? Well, you can return a reference to NULL, but then the burden is on the code making the call to remember to check and see if the & of the reffered-to object is NULL. (blech) Bite the bullet, throw exceptions. Don't return references. Create a default and plug it in, return that reference. Have a static "blank" or default no-value-found object and return a reference to it. 3. This code is from FAQ lite. class Point { public: static Point rectangular(float x, float y); // Rectangular coord's static Point polar(float radius, float angle); // Polar coordinates // These static methods are the so-called "named constructors" ... private: Point(float x, float y); // Rectangular coordinates float x_, y_; }; inline Point::Point(float x, float y) : x_(x), y_(y) { } inline Point Point::rectangular(float x, float y) { return Point(x, y); } inline Point Point::polar(float radius, float angle) { return Point(radius*cos(angle), radius*sin(angle)); } int main() { Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular Point p2 = Point::polar(5.7, 1.2); // Obviously polar ... } Dumb question. Now who owns p1 and p2 and how can I delete them? The local scope within the main() function owns the objects. Short answer - you don't delete them. The compiler generates code that deletes them (off the stack, not the heap!) when the function exits/returns. (or throws an exception) Jul 23 '05 #3

 P: n/a 1. That is not a copy constructor. A copy constructor is named the same as the class, has an implicit (that must be implicit) return type of void and gets a similar value to class_name const &ob as its only parameter. What you have implemented is a copy-assignment operator which is what is called when the class participates as an lvalue after it has been constructed. To illustrate this class_name cl = c; //Would call the copy constructor cl = c; //Would call the copy-assignment operator To clarify a bit more, copy constructors usually do not involve memcpying the other ob to the this pointer (neither does the copy-assignment operator for that matter). Normally, any non-pointermembers are copied by value using normal assignment statements and any pointer members are assigned new storage and the contents of the other object's pointer copied over. Also, just so you know, the test code, as you've implemented it, will do a standard assignment between the two pointers when assigning one to the other as the copy-assignment operator that you did implement takes as its implicit first parameter an object of type A and not type A*. 2. If you're returning a pointer to an object if it is found, then why would you declaring the function as reference and not pointer? I don't quite understand what you're trying to accomplish with it. 3. p1 and p2 are both local variables owned by the main function and are automatically deleted as they were allocated on the stack, that is, they needn't be deleted through any special syntax. Jul 23 '05 #4

 P: n/a "Phil Staite" wrote... MSR wrote: [...] 2. Null Reference. For example we have a function that searches a list and returns a pointer to an object if it is found or NULL if it can't find the object. How can I do this if I want to return a reference instead of a pointer, without throwing exceptions? Well, you can return a reference to NULL, [..] How? Jul 23 '05 #5

 P: n/a Do note, MSR, that the test code for your first question would not even invoke that copy assignment operator if it were attempting assignation and not copy construction. You overloaded operator = for objects of type A only and not A*, thus the assignation taking place is a standard scalar object to scalar object assignation resulting in the second pointer pointing to the same block of memory that the first is. Jul 23 '05 #6

 P: n/a Victor Bazarov wrote:Well, you can return a reference to NULL, [..] How? Not that any sane programmer would do this (but that apparently only rules out about 10% of us)... I've seen some stupid...er "heroic" things tried in order to fit into just the kinds of constraints the OP mentioned - return a ref, no exceptions... IMHO that's a good time for the designer/coder to "push back" on the requirements. But when they can't/won't you end up with "stuff" like this: #include class foo { public: void ident() { std::cout << "My address is: " << static_cast(this) << std::endl; } }; foo& stupidFunction() { return *static_cast(NULL); } int main(int argc, char* argv[]) { stupidFunction().ident(); return 0; } And a really bad "contract" with the caller of the function that they have to check that the reference they get back is in fact a real object. Ugh!!! Jul 23 '05 #8

 P: n/a PS - I'm almost ashamed to post that dereference a cast of a NULL code/construct. I don't want anyone to ever use it - so everyone forget you ever saw it. PPS - Drop the "almost" above... Jul 23 '05 #9

 P: n/a "Sep" wrote in message news:11**********************@o13g2000cwo.googlegr oups.com... 1. That is not a copy constructor. A copy constructor is named the same as the class, has an implicit (that must be implicit) return type of void and gets a similar value to class_name const &ob as its only parameter. What you have implemented is a copy-assignment operator which is what is called when the class participates as an lvalue after it has been constructed. To illustrate this class_name cl = c; //Would call the copy constructor cl = c; //Would call the copy-assignment operator To clarify a bit more, copy constructors usually do not involve memcpying the other ob to the this pointer (neither does the copy-assignment operator for that matter). Normally, any non-pointermembers are copied by value using normal assignment statements and any pointer members are assigned new storage and the contents of the other object's pointer copied over. Also, just so you know, the test code, as you've implemented it, will do a standard assignment between the two pointers when assigning one to the other as the copy-assignment operator that you did implement takes as its implicit first parameter an object of type A and not type A*. Thanks for the detailed explanation. I did confuse between copy constructor and copy assignmen operator 2. If you're returning a pointer to an object if it is found, then why would you declaring the function as reference and not pointer? I don't quite understand what you're trying to accomplish with it. I am returning a pointer to the object found because I couldn't find a way to return a reference to that object. I was trying to see, if I could acheive the same result by returning reference instead of a pointer. Using a pointer I would return a NULL if object not found in the list and I wanted to learn how I could do the same if I were to return a reference instead of a pointer. But from the previous replies, it became clear to me that it cant be (except for a serious piece of hack). 3. p1 and p2 are both local variables owned by the main function and are automatically deleted as they were allocated on the stack, that is, they needn't be deleted through any special syntax. My question, in the context of the code was really dumb. Please see my first reply to Victor's post, where I had new code that shows exactly what I wanted to know. Thanks once again Sep. Jul 23 '05 #11

 P: n/a "Victor Bazarov" , haber iletisinde şunları yazdı:lZ********************@comcast.com... "Phil Staite" wrote... MSR wrote: [...] 2. Null Reference. For example we have a function that searches a list and returns a pointer to an object if it is found or NULL if it can't find the object. How can I do this if I want to return a reference instead of a pointer, without throwing exceptions? Well, you can return a reference to NULL, [..] How? Well, I use a technique to pass a null reference from time to time. If it can be done, returning a null reference should also be possible. class Y { .... }; class X { public: Y& GetY() { if (some_error) return *(Y*)0; else return *(new Y); } }; Then of course you would need to check if it is a null reference. void myFunc() { Y& ry = X().GetY(); if ( &ry == 0 ) error_code; } Jul 23 '05 #12

 P: n/a On 12/3/05 9:35 PM, Aslan Kral wrote: { ... }; class X { public: Y& GetY() { if (some_error) return *(Y*)0; else return *(new Y); } }; Hi, I'm no C++ genius, but this code has to be "wrong". Even if it does compile, it has to be a bad idea, and means that your code is inherently unsafe. Surely the point of having references is not to allow things like this. void myFunc() { Y& ry = X().GetY(); if ( &ry == 0 ) error_code; } It's bad enough doing this sort of thing with pointers. Jul 23 '05 #13

 P: n/a "Richard Cavell" , haber iletisinde sunlari yazdi:d0**********@nnrp.waia.asn.au... On 12/3/05 9:35 PM, Aslan Kral wrote: { ... }; class X { public: Y& GetY() { if (some_error) return *(Y*)0; else return *(new Y); } }; Hi, I'm no C++ genius, but this code has to be "wrong". Even if it does compile, it has to be a bad idea, and means that your code is inherently unsafe. Surely the point of having references is not to allow things like this. You are right. It was just an exercise of returning a null reference. I don't think anybody would write something like that. void myFunc() { Y& ry = X().GetY(); if ( &ry == 0 ) error_code; } It's bad enough doing this sort of thing with pointers. Right but with pointers you should always consider the possibility for being null. Jul 23 '05 #14

 P: n/a "MSR" wrote... [...] Let me give modified code class Point { public: static Point* instance(); private: static Point* _instance; Point(); float x_, y_; }; inline Point* Point::instance() { if(_instance == 0){ _instance = new Point(); } return _instance; } inline Point::Point( ) : x_(0), y_(0) { } Point* Point::_instance=0; int main() { Point* p1 = Point::instance() ; ....... } Now who owns p1 and how can I delete it. This is a good question. Since Point::_instance, a copy of which you are given by the Point::instance() function, is a private member of the Point class, the Point class is the owner and it should delete it when nobody else needs that instance. Now, how you (on behalf of the Point class) determine that nobody needs it any longer is up to you. Basically, you have an example of a singleton here. There are several popular implementations of singletons, read about them and make your pick. What book are you reading that doesn't talk about copy construction and automatic variables? Actually I am not reading any book. I know I should. I know C and am working on C++ from that experience. I know C++ is different but then it is similar too. I got Stroustrup's book and will start reading soon. Beware that it's really jam-packed with information and you may need to work up quite a concentration to successfully digest it. Good luck! V Jul 23 '05 #15

### This discussion thread is closed

Replies have been disabled for this discussion.