Constructor called on an already created object

10,187

Solution 1

First off, the [c] tag is inappropriate since constructors are a C++-only feature. I'll assume the code snippet you provided is in fact C++ and not some weird dialect of C. C++ and C are different languages; do not tag your questions as both since you will get different answers for each.

Second, your constructor definition is wrong. Constructors must have the exact same name as the class itself. So f() should've been F(). Yes, case-sensitivity matters in C++! I'll assume this is what you meant for the rest of the code snippet. OP simply made a typo.

Before I explain what the rest of your code does, you must understand that all classes (and structs) in C++ have special member functions that are automatically generated by the compiler if you don't provide them. That is, your code snippet is basically the same as:

struct F
{
    F(int _a, int _b) {a = _a; b = _b};  // constructor
    ~F() {}                              // destructor
    F(const F& rhs)                      // copy constructor
        : a(rhs.a)
        , b(rhs.b)
        , c(rhs.c)
        , d(rhs.d)
    {}
    F& operator=(const F& a)             // copy assignment operator
    {
        a = rhs.a;
        b = rhs.b;
        c = rhs.c;
        d = rhs.d;
        return *this;
    }

    void a(int _a, int _b) {a = _a; b = _b};   // one of your functions

    int a;
    int b;
    int c;
    int d;
};

If you do not define a copy constructor, a copy assignment operator, or a destructor, the compiler will generate them for you. Also, if you don't provide some other constructor, the compiler will generate a default constructor. There is no default constructor for class F since there's already a (non-copy) constructor that accepts two arguments.

The default implementation of the copy constructor and the copy assignment operator simply copies each data member.

The reason why special member functions exist is because C++ generalizes the notion of copying primitive types to user defined objects. Consider this:

int a = 42;
int b = 13;
b = a;

With primitive types like ints, you can copy around its value just like that. C++ generalizes the copy semantics to objects so you can do this:

F f(10, 20); // calls first constructor
F g(30, 40); // calls first constructor
g = f;       // calls g's copy-assignment operator.

Now you can see how this applies to your code:

F f = F(5,6); 

The line above constructs a temporary F object, then copies the temporary into f via the copy constructor. The temporary F object is then destructed.

f = F(7,8);

The line above constructs another temporary F object, then assigns the temporary into f via the copy assignment operator. The temporary F object is then destructed. The original f object is not destructed.

f.a(9,0)   

The line above is a normal function call on an object called f.

For your code snippet, assuming compilers do not optimize away the temporaries (they in fact usually do), then calling the function a is "less resource intensive" since no temporaries are made in that case. However, for your first constructor call, you can just do this:

F f(5,6); // Constructor called; no temporaries are made

Understand what constructors are used for: they are used to create objects. If you already have an object, then you don't need to call a constructor.

As I have recommended many times, please pick up a good C++ book and read it. Special member functions and what they do are quite fundamental to C++.

Solution 2

(In the code you posted you've used a lower-case f instead of an upper-case F for the constructor, which I assume is a typo)

Your question is interesting because the question you've asked and the code you've written are not the same. In the code, you've written

f = F(7, 8);

This does call the F constructor, but not on the existing f object. Instead, this creates a temporary F object initialized by calling tue constructor with 7 and 8 as arguments, then uses the assignment operator to set the existing f variable equal to this new object. Consequently, the constructor is not invoked twice on the object; instead it's the assignment that gets called here. More generally, if you ever assign an existing object a new value, the assignment operator, not a constructor, will be used to do the copying. This will reuse the existing memory for the object, though it may trigger auxiliary memory allocations and deallocations.

There is no safe way to invoke an object's constructor twice. If you really do want to invoke the constructor of an object that's already been created, you can do so using placement new:

F f(3, 5);
new (&f) F(7, 9);

This is unsafe as it bypasses typical resource cleanup the destructors normally would do and blindly overrides the existing elements, so this is almost never done in practice. I mention it mostly for the sake of curiosity and for completeness. :-)

Solution 3

i'm ignoring the implementation in the OP, and going straight to the QA:

if i call a constructor on an already constructed object / struct, will it allocate new space

no, the object will not be reallocated. the constructor's implementation will be called (e.g. a function call).

So is the first object allocation more resource intensive?

you should generally not do this, unless you're implementing a collection (e.g. vector).

but, to answer the question: yes, the second will require fewer instructions. the compiler produces trivial instructions to set up the allocation (if on the stack or elsewhere). so there really is a few stages to creating an object automatically, and you are bypassing some of that. but seriously: don't consider this as an optimization -- only call the constructor/destructor manually if you absolutely must (again, think collection types).

Is the constructor call more res. intesive, than the call to a function which does the same (void a(...)) ?

potentially, the compiler's efforts also weigh in. remember, constructors and destructors call the implementation of each class in the hierarchy, so... it's quite likely that a singular function would be faster if your class hierarchy is non-trivial.

Does the destructor gets called, when i call a constructor on an already created object?

if you explicitly construct an object in this manner, then the answer is 'no'. it's your job to appropriately pair the explicit invocations. you cannot afford to implement this incorrectly, it's as good as UB. the order is always construct->destruct.

just to be clear of the syntax used:

// explicit ctor
new(ptr) T(ctorArgument);
// explicit dtor
ptr->~T();

Solution 4

There are syntatic mistakes in your program, modifying your snippet-

struct F {

    int a,b,c,d;

    F(int _a, int _b) {a = _a; b = _b}; 

    void a(int _a, int _b) {a = _a; b = _b};

};

F f = F(5,6); // Here the default copy constructor gets called.
              // i.e., F( const F& obj ) ;

f = F(7,8);   // A temporary is created is assigned to `f` through default copy assignment operator.
              // i.e., F& operator=( const F& obj );

Destructor gets called, when the constructed object goes out of scope ( ie., when the life time of the object completes).

Share:
10,187
Peter Lapisu
Author by

Peter Lapisu

At https://min60.com we deliver custom iOS, Android mobile applications for our clients...

Updated on July 02, 2022

Comments

  • Peter Lapisu
    Peter Lapisu almost 2 years

    If I call a constructor on an already constructed object or struct, will it allocate new space, or just use the existing space? So is the first object allocation more resource intensive? Like this:

    struct F {
        int a,b,c,d;
        F(int _a, int _b) {a = _a; b = _b}; 
        void a(int _a, int _b) {a = _a; b = _b};
    };  
    
    //first constructor call
    F f = F(5, 6);
    
    //second constructor call on an already constructed object
    f = F(7, 8);
    
    //third constructor call on an already constructed object
    f(7, 8);
    
    //is the constructor call more res. intesive, than the call to a function which does the same? 
    f.a(9, 0)
    

    Is the constructor call more resource intesive, than the call to a function which does the same (void a(...))?

    Does the destructor gets called, when I call a constructor on an already created object?