Thread: Copy constructor

  1. #16
    Registered User
    Join Date
    Dec 2005
    Posts
    136
    deep copies are, one has error and one is shallow copy!
    Code:
    a=b;
    *x=*y;
    S_ccess is waiting for u. Go Ahead, put u there.

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    a = b is not a shallow copy. Remember the types of a and b!
    But you did find the deep copy. So give your code, how would you make a deep copy? You can relate to the example (substitute for x and y, the pointers since your types are also pointers) if the answer isn't clear!
    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.

  3. #18
    Registered User
    Join Date
    Dec 2005
    Posts
    136
    i meant actually
    Following are the deep copies,
    Code:
    a = b;
    *y = *x;
    For the rest, One has the error and one is shallow copy.
    S_ccess is waiting for u. Go Ahead, put u there.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Correct. So how would you now implement your copy constructor to perform a deep copy?
    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.

  5. #20
    Registered User
    Join Date
    Dec 2005
    Posts
    136
    Hence it means, code will perform perfect deep copy.
    Code:
    dataPtr = d.dataPtr;

  6. #21
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Hence it means, code will perform perfect deep copy.
    O_o

    Nope.

    Elysia has given some clear examples.

    You are "shallow copying" by only copying a reference (pointer).

    That may be what you want, but it is not a "deep copy".

    Soma

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by maven View Post
    Hence it means, code will perform perfect deep copy.
    Code:
    dataPtr = d.dataPtr;
    Why do you think this is a deep copy?
    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.

  8. #23
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Exclamation

    Okay, there are several issues here:

    (1) Anytime the requirement for a deep copy of a pointer arises, you must consider the "Rule of Three". Incidentally, having to implement all of that (and doing it correctly) over and over get's REALLY old after a while! Fortunately, the use of some sort of smart pointer object is all that is needed to relieve you from such "manual" work.
    (2) Assigning the result of the "new" operator to anything other than a smart pointer is a violation of RAII and proper exception safety, and often leads DIRECTLY to the manifestation of bugs in your code. If anyone tells you different, they're just plain ignorant.
    (3) You should avoid native arrays except in the most trivial cases (lookup tables and the like). They just force you back into the dark ages of programming in C, as you have to constantly consider initialization and assignment issues, and are quite often the source of buffer overflow bugs. Use something like std::string, std::array, or std::vector instead.

    Yes, writing safe and robust programs in C++ does require the adherence to certain methodologies. That said, the techniques really aren't so complicated or difficult to learn, so nothing to worry about too much anyway...
    Last edited by Sebastiani; 06-18-2013 at 01:22 PM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #24
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Fortunately, the use of some sort of smart pointer object is all that is needed to relieve you from such "manual" work.
    O_o

    The original post actually shows a motivating counter example.

    Using a normal smart pointer doesn't "deep copy" the "pointee": the expression `*objptr1 = *objptr2' shares or transfers the resource owned by the smart pointer.

    Using a "cloning" smart pointer allows the expression `*objptr1 = *objptr2' to copy the "pointee", but a "cloning" smart pointer will require some form of a "clone" mechanisms which will generally be a method which will, itself, be easier to write using a copy constructor. The default form of the copy constructor could not be used because the default also copies the "cloning" pointer resulting in infinite recursion.

    The point here is that relying on the default "big three" is great when you are using facilities which take care of themselves, but you have to be mindful of constructs where "taking care of themselves" still does the wrong thing.

    Assigning the result of the "new" operator to anything other than a smart pointer is a violation of[...] proper exception safety.
    You don't need a smart pointer to get exception safety.

    In point of fact, you only need to isolate problematic constructs, ones that may raise an exception, behind a point of commit or rollback semantics using operations which do not raise exceptions. This isolation is simply what smart pointers do for client code.

    Now, I'm not, in any way, arguing that smart pointers should not be used. You should use smart pointers, and if at all possible, you should never manually destroy a resource.

    The point here is that exception safety is born of using exception safe constructs however they may look, and using smart pointers only get you so far.

    Code:
    template
    <
        typename FType
    >
    struct STest
    {
        STest():
            m(new FType); // Rollback or Success
        {
        }
        STest
        (
            const STest & f
        ):
            m(new FType(*f.m)) // Rollback or Success
        {
        }
        STest & operator =
        (
            const STest & fOther
        )
        {
            STest(fOther).swap(*this); // Rollback or Success
            return(*this);
        }
        ~STest()
        {
            delete m;
        }
        void swap
        (
            STest & fOther
        ) // This can't raise an exception as the underlying operations don't raise an exception.
        {
            using std::swap;
            swap(m, fOther.m);
        }
        FType * m;
    };
    In cases like this, where the acquisition of a resource is the crucial point of failure, you don't need a resource owning "RAII" object to do the work.

    Code:
    char * strdup
    (
        const char * fString
    )
    {
        char * sResult(new char[strlen(fString) + 1]); // Rollback or Success
        return(strcpy(sResult, fString)); // This does not raise an exception.
    }
    // ...
    char * DoConvert_imp
    (
        const char * fString
    )
    {
        char * sResult(strdup(fString)); // Rollback or Success
        // Use operations which do not raise exceptions, assigning `char' which are integers, to do case conversion.
        return(sResult);
    }
    // ...
    char * DoConvert
    (
        const char ** fString
    )
    {
        char * sResult(DoConvert_imp(*fString)); // Rollback or Success
        delete[] *fString; // We assume this can't raise an exception for the obvious reason.
        *fString = sResult; // We've only assigned a pointer which doesn't raise an exception.
        return(sResult);
    }
    Here I am using `char' and "C strings", but the same concepts, isolating crucial failures behind a single point of entry, apply to any type, collection, and algorithm which may be built from operations which do not raise exceptions once the critical point of failure has passed.

    Actually, this is exactly how resource owning "RAII" objects are developed which are more complex than smart pointers.

    Soma
    Last edited by phantomotap; 06-18-2013 at 03:08 PM.

  10. #25
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by phantomotap
    The point here is that relying on the default "big three" is great when you are using facilities which take care of themselves, but you have to be mindful of constructs where "taking care of themselves" still does the wrong thing.
    When I say "smart pointer", I'm simply refering to some sort of object to delegate the task of managing the pointer PROPERLY (however that may be). So long as the correct type of smart pointer is used (which of course may have to be coded "from scratch"), the Big Three will be taken care of.

    Quote Originally Posted by phantomotap
    You don't need a smart pointer to get exception safety...In point of fact, you only need to isolate problematic constructs, ones that may raise an exception, behind a point of commit or rollback semantics using operations which do not raise exceptions.
    Right, well sometimes it isn't even possible to "isolate" such things (consider passing directly new'ed objects as multiple parameters to a function, for instance). I say use a smart pointer and be done with it - eh?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #26
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Perhaps it would be a good time for you to have a go now, and post your attempt.

    The best way to handle a class (lets call it "foo"), which has a bunch of variables but only one of which requires special code for copying some object (lets call it "bar"), is to put that certain member into a class of its own (lets call it "moo"). "moo" contains only an instance of "bar" and handles just the copying of its "bar". Then in "foo", you can just use an instance of "moo" instead of an instance of "bar", and avoid having to implement the copy-constructor in "foo" at all. You're implementing the exact same operations on "bar", just in a different class. It simply stops you from having to specify how to copy all the other members which can already copy themselves.

    You need then only realise that rather than creating your own "moo", that you've just implemented your own smart pointer, and could probably just replace "moo" with one of the standard smart pointer types, if your assignment allowed of course.
    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"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. GCC and Copy Constructor
    By NA9x2000 in forum C++ Programming
    Replies: 7
    Last Post: 08-25-2012, 09:38 AM
  2. Copy constructor
    By dude543 in forum C++ Programming
    Replies: 26
    Last Post: 01-26-2006, 05:35 PM
  3. what is copy constructor?
    By Tonyukuk in forum C++ Programming
    Replies: 4
    Last Post: 12-10-2002, 05:54 PM
  4. Copy constructor
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 04-15-2002, 02:02 PM
  5. copy constructor
    By ygfperson in forum C++ Programming
    Replies: 6
    Last Post: 03-05-2002, 06:55 PM