Thread: CConstructor Infinite Recursion!

  1. #46
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    std::list::push_back, and push_back for any other STL container, uses a const reference.
    void push_back ( const T& x );

    Add element at the end
    Adds a new element at the end of the list, right after its current last element. The content of this new element is initialized to a copy of x.

    This effectively increases the list size by one.
    Code:
    while ( whatever ) {
       Dog save(stuff);
       
       a.push_back(save);
    }
    Incidentally, this (unasked) question is better than the earlier one. Most of the time, you just need to explain the real, actual problem, and delve not into hypotheticals. There are so many smart people here, it is unfair to other places.

  2. #47
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    std::list:ush_back, and push_back for any other STL container, uses a const reference.


    Code:
    while ( whatever ) {
       Dog save(stuff);
       
       a.push_back(save);
    }
    Incidentally, this (unasked) question is better than the earlier one
    I tried that, but it didn't work, because the save object would still go out of scope and the pointer would address would be destroyed.
    Yes, i think this is better because I know for sure the copy constructor would be called.

    Most of the time, you just need to explain the real, actual problem, and delve not into hypotheticals. There are so many smart people here, it is unfair to other places.
    I apologize, didn't mean to offend you or anyone .

    If i implemented to copy constructor so that when pushing to the list it copies using the defined constructor, the question is would it work?

  3. #48
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    OK, well there is no real difference between what I wrote and a.push_back( Dog(4,4) ); It is copied anyway according to the reference page. But the problem must be with your copy constructor if you are pushing invalid objects into a.

    I would want to see Dog's members and the available copy constructor to fix it.

  4. #49
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    OK, well there is no real difference between what I wrote and a.push_back( Dog(4,4) ); It is copied anyway according to the reference page. But the problem must be with your copy constructor if you are pushing invalid objects into a.

    I would want to see Dog's members and the available copy constructor to fix it.
    yeah that is the problem, i didn't even have a copy constructor.

    Code:
          class Dog
          {
                  char *name ; 
                  int a,  b ;
    
                  Dog(int x, int y) 
                  {
    
                          a = x; 
                           b = y  ;
    
                          name = new int[5] ;
                           name="Jack
                    }
    
                   ~Dog()
                    {
                             delete []name ;
                          // i think when it goes out of scope the destructor the destroys the                  
                          //memory location of name, but the object copied to the list would point to                
                           //that memory address, and when i accessed it later i got a seg fault.
                          //maybe this idea is wrong then. 
                     } 
    
    
           }

  5. #50
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    No, you are correct. When the Dog you passed to push_back goes out of scope the destructor will be called, but you copied that old address into a's copy of Dog. This is why default copy construction doesn't work for objects that have resources you need to manage.

    Even changing name to std::string would solve Dog's problems, because you don't have to manage memory.

  6. #51
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    No, you are correct. When the Dog you passed to push_back goes out of scope the destructor will be called, but you copied that old address into a's copy of Dog. This is why default copy construction doesn't work for objects that have resources you need to manage.

    Even changing name to std::string would solve Dog's problems, because you don't have to manage memory.

    Oh yes, you caught me out haha.
    Well, in truth i am making a using allegro and i wasn't using c string, but
    a function called create_bitmap(..) and that uses the free store.

    I just thought simplifying it to strings would make discussion easier.

    And yes! I just tried it, it absolutely worked! I was able to use destructor as normal and it looks cleaner.

    Maybe copy constructors aren't so bad hahaha.

    Thanks very much man.

  7. #52
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    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.
    I wrote that example in quite a hurry. I could have virtually guaranteed that it was buggy, but it seems to have illustrated the point well enough.
    I should also point out that it's completely useless since there are no ways to access the stored data.
    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"

  8. #53
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    >>I wrote that example in quite a hurry

    And that's OK. I was only trying to respond to Eman's questions.

  9. #54
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    Hey, so I wrote the idea down on paper.

    so I think maybe I can understand what you meant by infinite recursion. If i go back to function call basics.
    Code:
      void foo(int a) ;  
       main()
       {
            foo(10) ; 
       }
    Steps
    1. main invokes the foo function.
    2. the compiler/OS sets about to make a copy of 10 and assigns a the copied value.
    3. function call ends.
    now if i apply that basic concept, then the theory of infinite recursion makes sense

    Code:
          class A 
          {
                A(A a) 
               {
                          // we assume it will compile
               }
           } ;
           main() 
          {
                 A a ;
    
                 B b(a) ;
    
          }
    Steps
    "B b(a)" naturally will invoke a function call.
    1. Copy constructor is invoked. We've already defined one, so compiler issues that.
    2. Compiler/OS (i'm not sure which, but I assume it is the OS, makes more sense) proceeds to make a copy of the object in the parameter.
    But wait it is an object, and what makes copies of object? A copy constructor! Copy constructor is invoked.
    3. Compiler proceeds to make a copy of the parameter. Hold on, it is an object. What makes copies of objects? A copy constructor! We've defined one. and so it goes on.

    Infinite recursion...

    But for pass by reference
    Code:
              class A 
             {
                    A(A &a) 
                   {
                         // we assume it will compile
                    }
              } ;
             main() 
            {
                   A a ;
    
                   B b(a) ; 
    
             }
    Steps
    1. Copy constructor is invoked.
    2. Compiler proceeds to make copy of parameter.
    3. It is not a object, but a reference to the object.
    4. The compiler makes a copy of the address and stores the address to the copy constructor parameter. The compiler automatically dereferences it for us, which makes all the difference between references and compiler. (Simply the compiler makes a reference to the constructor parameter)
    5. Copy Constructor exits.
    No infinite recursion.

    So I was going through all this on paper, to really "see" what was happening. and I think the "algorithm" of what happens might be what you meant.
    Going through it feels correct and makes sense.

    Is it correct?
    Thanks

  10. #55
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by iMalc View Post
    I should also point out that it's completely useless since there are no ways to access the stored data.
    What do you mean, what is useless?

  11. #56
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The only thing to note is that a copy constructor behaves like a real function.
    If you have
    Code:
    foo(A a)
    Then the compiler will generate code to make a copy of the object which is passed to foo. It does this by calling the copy constructor. But a copy constructor is a function, like everything else.
    So if you have
    Code:
    A::A(A a)
    Then the compiler must generate code to make a copy of the object passed into the copy constructor. And the problem is, of course, that the object's type is the same type as the copy constructor's. So it would invoke A's copy constructor. Again. And so on.

    Now take note that references are aliases and not addresses.
    Code:
    A& a = b;
    In this example, a is simply another name for b.
    But no copy is made because we're just creating an alias.

    Now, you seem to be running into SourceForge.net: Raw pointer issues - cpwiki. Suggest you read it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #57
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by Elysia View Post
    The only thing to note is that a copy constructor behaves like a real function.
    If you have
    Code:
    foo(A a)
    Then the compiler will generate code to make a copy of the object which is passed to foo. It does this by calling the copy constructor. But a copy constructor is a function, like everything else.
    So if you have
    Code:
    A::A(A a)
    Then the compiler must generate code to make a copy of the object passed into the copy constructor. And the problem is, of course, that the object's type is the same type as the copy constructor's. So it would invoke A's copy constructor. Again. And so on.

    Now take note that references are aliases and not addresses.
    Code:
    A& a = b;
    In this example, a is simply another name for b.
    But no copy is made because we're just creating an alias.
    So, because the objects type is the same as the object passed to the copy constructor, it will keep calling the same copy constructor.
    So which means if i pass by value an object but of a different type. It shouldn't give me an infinite loop, unless they share the same copy constructor - in this case i would be thinking of inheritance... ?


    Now take note that references are aliases and not addresses.

    In some website i read it says references act like pointers, except the addresses are dereferenced for us, which makes it cleaner. So we can use as local variables. I get your point that they are aliases.

  13. #58
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Eman View Post
    So, because the objects type is the same as the object passed to the copy constructor, it will keep calling the <b>same<b> copy constructor.
    So which means if i pass by value an object but of a different type. It shouldn't give me an infinite loop, unless they share the same copy constructor - in this case i would be thinking of inheritance... ?
    Indeed, so it would invoke that other object's copy constructor, and unless it does something weird, you shouldn't get infinite recursion.

    <b>Now take note that references are aliases and not addresses.</b>

    In some website i read it says references act like pointers, except the addresses are dereferenced for us, which makes it cleaner. So we can use as local variables. I get your point that they are aliases.
    All I can say is that the standard says that they are aliases. Different names for the same object. How the compiler implements references is another matter. That is implementation specific. That is, compiler vendors can choose how they want to do it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #59
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by Elysia View Post
    Indeed, so it would invoke that other object's copy constructor, and unless it does something weird, you shouldn't get infinite recursion.

    i hope there is no ban on excessive use of smiley, i just can't help it!
    Now i truly understand it.

    All I can say is that the standard says that they are aliases. Different names for the same object. How the compiler implements references is another matter. That is implementation specific. That is, compiler vendors can choose how they want to do it.
    Yeah true. References confused me for a while, i didn't really understand what it meant until I figured out for references to work, they must have the same addresses, no matter how different each compiler optimizes it. Which is why we have to initialize references on declaration, except if references were to be used with function calls.

  15. #60
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    Why does STL invoke copy constructor.

    Em. Does anyone know why a pushing an object into a list invokes the copy constructor?
    I just had a glance at the api and noticed it takes a reference to an object. So it shouldn't invoke it, but it does?

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