Like Tree2Likes
  • 1 Post By grumpy
  • 1 Post By laserlight

Copy constructor issue.

This is a discussion on Copy constructor issue. within the C++ Programming forums, part of the General Programming Boards category; Hello, I'm new to both to this site and to C++, I've started reading the book 'C++ Without Fear - ...

  1. #1
    Registered User
    Join Date
    Jan 2012
    Posts
    3

    Post Copy constructor issue.

    Hello, I'm new to both to this site and to C++, I've started reading the book 'C++ Without Fear - 2nd edition' a couple of week ago. when I reached chapter 12 (which is about constructors) I got stuck on the subject of copy constructors, and I seek your help!

    (Example 12.3 from page 325 to page 329)

    This is the Fraction class declaration.
    Code:
    class Fraction
    {
        private:
            int num;
            int den;
        public:
            Fraction() {set(0, 1);} // Default constructor.
            Fraction(int n, int d) {set(n, d);} // (int, int) constructor.
            Fraction(Fraction const &src); // Copy constructor.
            
        void set(int n, int d)  {num = n; den = d; normalize();}
            int get_num()   {return num;}
            int get_den()   {return den;}
            Fraction add(Fraction other);
            Fraction mult(Fraction other);
        private: // Member functions (Private).
            void normalize();
            int gcf(int a, int b);
            int lcm(int a, int b)   {return (a * b) / gcf(a, b);}
    };
    This is the copy constructor definition.
    Code:
    Fraction::Fraction(Fraction const &src)
    {
        cout << "Now calling copy constructor!" << endl;
        
        num = src.num;
        den = src.den;
    }

    This is the main() function.
    Code:
    int main()
    {
            Fraction f1(3, 4);
            Fraction f2(f1);
            Fraction f3 = f1.add(f2);
    
            cout << "The value of f3 is ";
            cout << f3.get_num() << "/";
            cout << f3.get_den() << endl;
        
            return 0;
    }
    In the book it is said that the next line of code should call the copy constructor once (printing the "Now calling copy constructor!") Which it dose!
    Code:
    Fraction f2(f1);
    However the book also say that the next line of code should call the copy constructor three times!
    first time when the object f2 is passed as an argument,
    a second time when a new object is passed back as a return value,
    and a third time when that object is copied to the f3 object.
    Code:
    Fraction f3 = f1.add(f2);
    But when I run this program, it prints the above message only twice (instead of 4 times!!).

    I was thinking it must be the compiler optimizing the add member function, making it pass references instead of a copy of the object,
    but I don't really have any idea if I'm right.

    Am I making any sense or am I way off?
    I'd really appreciate if anyone can help me understand how and why the thing I described happens!

    (Btw I'm using both Code::Blocks and Dev-C++ IDE)

    Thanks ahead C.

    P.S. Sorry for my English!
    Last edited by IndicaHybrid; 01-05-2012 at 12:54 AM.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,157
    Quote Originally Posted by IndicaHybrid View Post
    However the book also say that the next line of code should call the copy constructor three times!
    first time when the object f2 is passed as an argument,
    a second time when a new object is passed back as a return value,
    and a third time when that object is copied to the f3 object.
    Code:
    Fraction f3 = f1.add(f2);
    The book is wrong. A literal interpretation of the code suggests the sequence of events described. However, that sequence of events implies the creation and destruction of temporary objects (objects that only exist while the particular statement is being executed).

    Section 12.8 para 15 of the C++ standard explicitly allows the compiler to avoid creating a temporary object if the only way of detecting its existence is by tracking constructor and destructor calls.

    This allows various optimisations by the compiler, such as the "Return Value Optimisation", which avoid unnecessary creation, copying, and deletion of objects.

    Different compilers may employ different strategies in deciding what temporaries can be avoided. The standard allows a compiler to do such optimisations, but does not make such optimisations mandatory.
    manasij7479 likes this.
    Right 98% of the time, and don't care about the other 3%.

  3. #3
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by grumpy View Post
    Section 12.8 para 15 of the C++ standard explicitly allows the compiler to avoid creating a temporary object if the only way of detecting its existence is by tracking constructor and destructor calls..
    Thanks.. I did not know that..
    But wouldn't that lead to shallow copy problems?.... if..say.. a member function returns an iterator which wraps around a pointer.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by manasij7479
    But wouldn't that lead to shallow copy problems?.... if..say.. a member function returns an iterator which wraps around a pointer.
    How is that a problem?
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by laserlight View Post
    How is that a problem?
    :doh: Now as I think about it.... it seems to not be a problem...but a feature.

    But I surely there can be some example where a return was really meant to be deep copied or copy constructed.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by manasij7479
    But I surely there can be some example where a return was really meant to be deep copied or copy constructed.
    Copy constructor elision does not change a deep copy to a shallow copy: it simply removes the copying through the copy constructor altogether. Consequently, if that copy constructor invocation was required, then that is a bug with the design or implementation of the class.
    iMalc likes this.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,288
    In my opinion, the book is wrong for suggesting that a copy-constructor even be implemented for this class. It is better to let the compiler generate this on its own in this case.
    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. #8
    Registered User
    Join Date
    Jan 2012
    Posts
    3
    Quote Originally Posted by grumpy View Post
    The book is wrong. A literal interpretation of the code suggests the sequence of events described. However, that sequence of events implies the creation and destruction of temporary objects (objects that only exist while the particular statement is being executed).

    Section 12.8 para 15 of the C++ standard explicitly allows the compiler to avoid creating a temporary object if the only way of detecting its existence is by tracking constructor and destructor calls.

    This allows various optimisations by the compiler, such as the "Return Value Optimisation", which avoid unnecessary creation, copying, and deletion of objects.

    Different compilers may employ different strategies in deciding what temporaries can be avoided. The standard allows a compiler to do such optimisations, but does not make such optimisations mandatory.
    So I was kinda right about the optimization?
    and by the way do you have any tips or suggestions for books or any other kind of information sources I could use?
    I'm still in the process of learning the language so I really want to make sure I understand what really happens here

    Thanks a lot for your response!!!

  9. #9
    Registered User
    Join Date
    Jan 2012
    Posts
    3
    Quote Originally Posted by iMalc View Post
    In my opinion, the book is wrong for suggesting that a copy-constructor even be implemented for this class. It is better to let the compiler generate this on its own in this case.
    This was the first time a copy constructor was introduced in the book, so I'm guessing the author just wanted to teach the novice readers (like me) about the basic features of this kind of a constructor

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with copy constructor
    By C_programmer.C in forum C++ Programming
    Replies: 4
    Last Post: 06-07-2011, 07:31 AM
  2. Copy constructor
    By dude543 in forum C++ Programming
    Replies: 26
    Last Post: 01-26-2006, 04:35 PM
  3. Linked list copy constructor issue
    By Craptastic! in forum C++ Programming
    Replies: 1
    Last Post: 08-03-2003, 08:30 PM
  4. copy constructor
    By Eber Kain in forum C++ Programming
    Replies: 1
    Last Post: 09-30-2002, 05:03 PM
  5. copy constructor
    By ygfperson in forum C++ Programming
    Replies: 6
    Last Post: 03-05-2002, 05:55 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21