Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor called on an already created object

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?

like image 558
Peter Lapisu Avatar asked Feb 18 '11 08:02

Peter Lapisu


People also ask

Can we call constructor after creating object?

No, you cannot call a constructor from a method.

Is a constructor automatically called when an object is created?

If members have default constructors or constructor without parameter then these constructors are called automatically, otherwise parameterized constructors can be called using Initializer List.

Which constructor gets invoked when an object is created?

Every time an object is created using the new() keyword, at least one constructor is called. It calls a default constructor if there is no constructor available in the class. In such case, Java compiler provides a default constructor by default.

Can we call constructor again?

Constructor is called automatically when we create an object using new keyword. It is called only once for an object at the time of object creation and hence, we cannot invoke the constructor again for an object after it is created.


2 Answers

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++.

like image 91
In silico Avatar answered Sep 21 '22 22:09

In silico


(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. :-)

like image 23
templatetypedef Avatar answered Sep 25 '22 22:09

templatetypedef