Skip to main content
gamedev.net
🔒 Locked

is this an assignment or constructor call ? it behaves as if it is both

Started by CoB_ChrizZz 8 replies 1.3k views
Original Post
CoB_ChrizZz
CoB_ChrizZz
Hi, i got trouble to understand the following call in the main():
a =20;


class X {
private:
int data;
public:
~X()
{
cout << "Destruktor " << data << '\n';
}
X(int d = -1) : data(d)
{
cout << "Allgemeiner Konstruktor " << data << '\n';
}
X(const X &x) : data(x.data)
{
cout << "Kopierkonstruktor " << data << '\n';
}
X& operator=(const X& x) //nimmt auch Konstanten (wie in etwa 20)
{
data = x.data;
cout << "Zuweisungsoperator " << data << '\n';
return *this;
}
void set(int d)
{
data = d;
}
int get()
{
return data;
}
};

X a(0);

int main()
{
cout << '\n' << "Start main" << '\n';
X a; // Allgemeiner Konstruktor -1
a =20;
// Allgemeiner Konstruktor 20
// Zuweisungsoperator 20
// Destruktor 20


char g;
cin >> g;
return 0;
}


basicly a = 20 should be an assignment by using the assignment operator.
But it also works without the assignment operator.
It would just print out:
Allgemeiner Konstruktor 20
Destruktor 20

instead.

So what happens here ? can't the compiler decide wether ist is an assignment or a constructor call ?
why is this ?
and why is there an destructor call ? it's definetely not because it reaches the end of the programm..because it still awaits "cin >> f"
Waterlimon
Waterlimon
For the destructor call, maybe it detects that you are not going to use the variable anymore, and thus destroys it before reaching the end of the block.
o3o
Evil Steve
Evil Steve
You don't have an operator=() defined that takes an int, so the compiler is having to create an X instance from the int, and assign a to that.

EDIT: And Waterlimon is correct about the destructot call - it's the temporary X instance being destroyed.
frob
frob
This is called "conversion by constructor" in the language standard.

Here is the example they use in the language standard


struct X {
X(int);
X(const char*, int =0);
};
void f(X arg) {
X a = 1; // a = X(1)
X b = "Jessie"; // b = X("Jessie",0)
a = 2; // a = X(2)
f(3); // f(X(3))
}
CoB_ChrizZz
CoB_ChrizZz
Thank you guys but i still have some uqestions ^^;

The compiler creates automaticly a constructor with 20 as value AND then assigns 20 to it, which doesn't change anything at all ?
I mean i would understand if the compiler would create a new instance of X with -1 as default parameter and then assign 20 to it.

And what makes "a" temporary ? it doesn't run out of scope but is destroyed ? i never saw this beahaviour before. Does this depend on the c++ compiler i am using ?
or is this a determined thing even before runtime ?

sorry for my noobish question but i have an important test on friday and i really wanna understand things more in depth :/

thank you very much !
Brother Bob
Brother Bob
If it helps to clear up your confusion, the code is equivalent to this:
[source]
X a;
a = X(20);
[/source]
It is not a that is destroyed, but the temporary value X(20) that has to be created in ordet to perform the assignment to a.

What happens is:

  1. Default-construct the named variable a.
  2. Construct a temporary object from the integer 20.
  3. Assign the temporary object to the named variable a.
  4. Destroy the temporary object.

Step 2 is what causes the program to print that the constructor with value 20 is called.
Step 4 is what causes the program to print that the destructor is called.
CoB_ChrizZz
CoB_ChrizZz
super, thank you Brother Bob. That cleared my whole confusion about this issue !!!

and thanks to all the other guys again who basicly said the same but i misinterpreted the thing about the temporary variable ;)
Adam_42
Adam_42
If you change your constructor declaration to:

explicit X(int d = -1) : data(d)


You won't get the confusing automatic type conversions. You have to manually call the constructor if you want them.
c_olin
c_olin
For the destructor call, maybe it detects that you are not going to use the variable anymore, and thus destroys it before reaching the end of the block.


The compiler can do that? Doesn't that essentially break RAII? For example, how could std::scope_lock work if the compiler could do this?
Brother Bob
Brother Bob

[quote name='Waterlimon' timestamp='1328624848' post='4910504'] For the destructor call, maybe it detects that you are not going to use the variable anymore, and thus destroys it before reaching the end of the block.


The compiler can do that? Doesn't that essentially break RAII? For example, how could std::scope_lock work if the compiler could do this?
[/quote]
It cannot.

As with any compiler optimization, the compiler can only optimize code as long as the observable behavior of the code does not change. If the compiler can destroy an object earlier without any side effects, then I don't know of any reason why it should not be able to do so. Now, since the destructor in the OP's code, and in RAII in general since you mentioned it, has side effects (OP's code is outputting text, and RAII typically release a resource), it cannot be performed earlier since that would change the observable behavior of the program.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.