Thread: CConstructor Infinite Recursion!

  1. #31
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    >>The code is an exact same which makes me wonder why the replication? What is the point of using an overloaded operator at all?

    It is not the same. In situations where operator= is appropriate, you are making one of two distinct pre-existing objects like the other such that they would compare equally, provided operator== isn't overloaded to do something stupid. In situations where copy construction is appropriate, you are initializing a new object using another object of the same type, such that both objects will compare equally.

  2. #32
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    I noticed that most tutorials always overloaded the operator '=' when creating a copy constructor.
    The code is an exact same which makes me wonder why the replication? What is the point of using an overloaded operator at all?
    A rule of thumb is that when you define the destructor, copy constructor or copy assignment operator, you should define all three (except when you are just defining a destructor as virtual, or when you are just declaring the copy constructor and copy assignment operator private so as to disable copying).

    The reason is that usually if you have to implement any of them, it means that you would be managing some resource manually in the class, and you would want to destroy the resource when the object is destroyed (or implement reference counting, etc), and you would want copy construction and copy assignment to behave in a similiar and consistent way.

    Quote Originally Posted by Eman
    2. A programmer might do this naturally
    Dog a = b;
    hence overloading the = operator
    Actually, that would invoke the copy constructor.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #33
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post

    Actually, that would invoke the copy constructor.

    that would invoke the copy constructor we defined ourselves, if we were using deep copy, not the default copy constructor the compiler writes for us, i assume.

    By managing resources you mean, it makes the compiler do less work- the compiler doesn't generate code for the destructor,constructor,copy constructor, and we know where error?

    Ah, this might seem a ridiculous question to you, but I am really slow.

  4. #34
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    >>The code is an exact same which makes me wonder why the replication? What is the point of using an overloaded operator at all?

    It is not the same. In situations where operator= is appropriate, you are making one of two distinct pre-existing objects like the other such that they would compare equally, provided operator== isn't overloaded to do something stupid. In situations where copy construction is appropriate, you are initializing a new object using another object of the same type, such that both objects will compare equally.
    What i mean is the code to copy the existing object to the other object is almost identical to the copy constructor we defined, if we defined one.

    The only difference I could see was that in the operator overloading operator=
    an if statement was done on the pointers to see if self copying was done and then a return.
    Apart from that the copying code is the same.

  5. #35
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    that would invoke the copy constructor we defined ourselves, if we were using deep copy, not the default copy constructor the compiler writes for us, i assume.
    No, that would invoke the copy constructor. If you declared it, it would invoke that one. If you didn't, it would invoke the default.

    Quote Originally Posted by Eman
    By managing resources you mean, it makes the compiler do less work- the compiler doesn't generate code for the destructor,constructor,copy constructor, and we know where error?
    No, I mean resources like memory.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #36
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Eman View Post
    What i mean is the code to copy the existing object to the other object is almost identical to the copy constructor we defined, if we defined one.

    The only difference I could see was that in the operator overloading operator=
    an if statement was done on the pointers to see if self copying was done and then a return.
    Apart from that the copying code is the same.
    Yes, you can implement operator= in terms of copy construction, but they are not the same operation, for the semantic reason I pointed out. If it confuses you, you don't strictly have to implement operator= in terms of copy construction, but that is what is usually easiest.

  7. #37
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    No, that would invoke the copy constructor. If you declared it, it would invoke that one. If you didn't, it would invoke the default.


    No, I mean resources like memory.
    oh yeah,
    it would be the memberwise assignment operator so a shallow copy would be done.

    [QUOTE]
    No, I mean resources like memory.
    [\QUOTE]

    Maybe if i had a dynamically allocated variable/object and I wanted to destroy it...


    [QUOTE]
    It is not the same. In situations where operator= is appropriate, you are making one of two distinct pre-existing objects like the other such that they would compare equally, provided operator== isn't overloaded to do something stupid. In situations where copy construction is appropriate, you are initializing a new object using another object of the same type, such that both objects will compare equally.

    for the semantic reason I pointed out.
    [\QUOTE]

    yeah, I don't fully understand what you meant by that statement.

    it would make sense if the operator== was overloaded to check if 2 objects were the same, why would you say that was stupid?

    I just thought that apart from how the execution of the Copy constructor and the operator= are different
    , the copying is the almost same.

  8. #38
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    OK, apparently I need to break down my post.
    It is not the same. In situations where operator= is appropriate, you are making one of two distinct pre-existing objects like the other such that they would compare equally,
    A comma signals a pause, so let's try to grasp what needs to be comprehended. Let's make a program to compare my two dogs. We create the Dog class and make two objects:

    Code:
    Dog freckles("Freckles");
    Dog tula("Tula");
    
    // freckles = tula;
    
    if ( freckles == tula ) {
       cout << "They are the same\n";
    }
    else {
       cout << "They are different\n";
    }
    If and only if the commented line is executed would you get the "same" result. So this exemplifies what it means to make two distinct pre-existing objects compare equally.



    provided operator== isn't overloaded to do something stupid.
    Now, since operator== is also overloadable, you cannot trust the if condition unless operator== is working as it should. You could make a fundamental mistake, like add a member to the Dog object and not change the comparison operator, and it would result in some objects comparing alike that are not. Or even "stupider" than that, similar to how you can implement plus to be minus.

    In situations where copy construction is appropriate, you are initializing a new object using another object of the same type, such that both objects will compare equally.
    To understand this part of my post, I think the only difference is the definitions of pre-existing and new. Specifically, a new object doesn't pre-exist, you are making it. The caveat about equality still applies, but I need not repeat myself.

  9. #39
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    OK, apparently I need to break down my post.


    A comma signals a pause, so let's try to grasp what needs to be comprehended. Let's make a program to compare my two dogs. We create the Dog class and make two objects:

    Code:
    Dog freckles("Freckles");
    Dog tula("Tula");
    
    // freckles = tula;
    
    if ( freckles == tula ) {
       cout << "They are the same\n";
    }
    else {
       cout << "They are different\n";
    }
    If and only if the commented line is executed would you get the "same" result. So this exemplifies what it means to make two distinct pre-existing objects compare equally.




    Now, since operator== is also overloadable, you cannot trust the if condition unless operator== is working as it should. You could make a fundamental mistake, like add a member to the Dog object and not change the comparison operator, and it would result in some objects comparing alike that are not. Or even "stupider" than that, similar to how you can implement plus to be minus.


    To understand this part of my post, I think the only difference is the definitions of pre-existing and new. Specifically, a new object doesn't pre-exist, you are making it. The caveat about equality still applies, but I need not repeat myself.

    Excellent, I understand what you mean.
    I think I understand copy constructors a lot better now thanks!
    Thanks a lot for your patience .

  10. #40
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Eman View Post
    I noticed that most tutorials always overloaded the operator '=' when creating a copy constructor.
    The code is an exact same which makes me wonder why the replication? What is the point of using an overloaded operator at all?
    They have different jobs to do. Most of the time in the real world they are actually different, but in a few cases (usually when they aren't actually necessary to implement anyway) they can look the same.

    The copy constructor's job is to create a copy into a completely uninitialised object.
    The assignment operator's job is to replace the contents of an initialised object with different contents.

    E.g. a class that holds a pointer to a string. The copy constructor just allocates a new array and copies the string over to it. The assignment operator however also has to delete the string originally held within the object:
    Code:
    class mystring {
        char *s;
    public:
        mystring() : s(NULL) {}
        mystring(char *s2) : s(new char[strlen(s2)+1] {
            strcpy(s, s2);
        }
        // copy constructor
        mystring(const mystring &rhs) : s(new char[strlen(rhs.s)+1] {
            strcpy(s, rhs.s);
        }
        // assignment operator
        operator = (const mystring &rhs) {
            char *s3 = new char[strlen(rhs)+1];
            delete []s; // The crucial difference here
            s = s3;
            strcpy(s, rhs.s);
        }
        ~mystring() {
            delete []s;
        }
    };
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #41
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by iMalc View Post
    Code:
            delete []s; // The crucial difference here
    Hi, yeah I was going to ask about that. But was afraid to ask too much lol.

    It would make sense that the "crucial difference" was not included in the copy constructor because the object does not already exist and therefore does not have the string s allocated memory.
    That should cause a seg fault.

    But using delete []s or some other like that, am I correct that in this case
    we are assuming that this object might already have been declared and data written to it.

    So if that is the case we want to overwrite that data, i think it could cause
    internal/external fragmentation or something like that I learnt in OS last year. because the string length might change.

  12. #42
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Even when s is NULL, delete []s; is going to be safe. It is a well defined operation. Nothing happens. What is troublesome is strlen (it will dereference a NULL pointer if rhs.s is NULL)
    Last edited by whiteflags; 12-21-2010 at 12:59 PM.

  13. #43
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    Even when s is NULL, delete []s; is going to be safe. It is a well defined operation. Nothing happens. What is troublesome is strlen (it will dereference a NULL pointer if rhs.s is NULL)
    that's cool then, but it would still be redundant to have it there.. in the cCtor?
    oh wow thanks for pointing that out, I didn't know strlen could do that
    So if that is the case it is a good idea to check if the string has data.

  14. #44
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It's an even better idea to not have the default construction be a NULL string. Real string classes allocate a small chunk, even if it is going to be an empty string.

  15. #45
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    It's an even better idea to not have the default construction be a NULL string. Real string classes allocate a small chunk, even if it is going to be an empty string.
    noted

    The reason for learning this I was trying to push objects into a list

    and i was doing it this way
    a.push_back(Dog(4,4)) ;

    and i kept getting segmentation fault error.

    And when i looked at my code, I realized that there was a dynamically created variable which my destructor destroyed when object was out of scope.

    And since a list just copies the values the temp object has the pointer in the object list would point to an address in a variable that was valid but then destroyed.

    I didn't know how to fix it so I had to do it manually and that sucked.

    I am not sure if list uses copy constructor to copy objects, I hope it does, if it does it can solve my problem . I would be able to use the destructor to destroy the free store
    and the objects in the list would point to valid addresses.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Template Recursion Pickle
    By SevenThunders in forum C++ Programming
    Replies: 20
    Last Post: 02-05-2009, 09:45 PM
  2. convert Recursion to linear can it be done
    By umen242 in forum C++ Programming
    Replies: 2
    Last Post: 10-15-2008, 02:58 AM
  3. Recursion... why?
    By swgh in forum C++ Programming
    Replies: 4
    Last Post: 06-09-2008, 09:37 AM
  4. Recursion
    By Lionmane in forum C Programming
    Replies: 11
    Last Post: 06-04-2005, 12:00 AM
  5. a simple recursion question
    By tetra in forum C++ Programming
    Replies: 6
    Last Post: 10-27-2002, 10:56 AM