Reason of additional destructor call? - c++

Given is the following simple class:
#include <iostream>
class Foo{
int a, b;
public:
Foo(int _a = 0, int _b = 0) : a(_a), b(_b) {
std::cout << "Foo(int, int)" << "\n";
}
Foo(const Foo& foo) : a(foo.a), b(foo.b) {
std::cout << "Foo(const Foo&)" << "\n";
}
Foo& operator=(const Foo& other) {
std::cout << "operator=(const Foo&)" << "\n";
if(this != &other){
a = other.a;
b = other.b;
}
return *this;
}
~Foo() {
std::cout << "~Foo()" << "\n";
}
Foo operator+(const Foo& other){
std::cout << "foo.operator+(const Foo&)" << "\n";
return Foo(a + other.a, b + other.b);
}
};
and the main:
int main(){
Foo f1, f2(1, 2), f3;
std::cout << "-----------" << "\n";
f3 = f1 + f2; // (*)
std::cout << "-----------" << "\n";
return 0;
}
I compiled with -std=c++11 and for demonstration purposes also with the -fno-elide-constructors flag. The output reads as:
Foo(int, int)
Foo(int, int)
Foo(int, int)
-----------
foo.operator+(const Foo&) // (1)
Foo(int, int) // (2)
Foo(const Foo&) // (3)
~Foo() // (4)
operator=(const Foo&) // (5)
~Foo() // (6)
-----------
~Foo()
~Foo()
~Foo()
As far as I understand it correctly, the following happens for the line f3 = f1 + f2; (*):
Obviously, f1.operator+(f2) is called.
A new (temporary) object is created. Let's denote it by T.
Since the operator+() function does not return a reference, we call to copy constructor in order to construct a copy T2 of T. We return T2.
The destructor is called in order to delete the temporary object T.
We call the copy assignment operator to assign all members of T2 to f3.
My question: I don't really see what's the purpose of (6). Why is there an additional call to the destructor, i.e. what am I missing here?

what am I missing here?
The destruction of T2.
There are 3+2 constructors called, there must be 3+2 destructors called too!

Related

Unexpected default constructor call when using move semantics

I have two similar pieces of code. The first version unexpectedly calls the default constructor while the second doesn't. They both call the move operator / move constructor, respectively, as expected.
class MyResource
{
public:
MyResource() : m_data(0) { std::cout << "Default Ctor" << std::endl; }
MyResource(int data) : m_data(data) { std::cout << "Int Ctor" << std::endl; }
MyResource(MyResource const& other) = delete;
MyResource& operator=(MyResource const& other) = delete;
MyResource(MyResource&& other) noexcept : m_data(other.m_data) { std::cout << "Move Ctor" << std::endl; }
MyResource& operator=(MyResource&& other) noexcept { std::cout << "Move Op" << std::endl; m_data = other.m_data; return *this; }
~MyResource() { std::cout << "Dtor" << std::endl; }
private:
int m_data = 0;
};
class MyWrapper
{
public:
MyWrapper(MyResource&& resource)
// : m_resource(std::move(resource)) // Version 2
{
// m_resource = std::move(resource); // Version 1
}
private:
MyResource m_resource;
};
My test usage is:
MyWrapper* wrapper = new MyWrapper(MyResource(1));
delete wrapper;
With Version 1, I get:
Int Ctor
Default Ctor
Move Op
Dtor
Dtor
While Version 2 outputs:
Int Ctor
Move Ctor
Dtor
Dtor
What's the reason behind this difference?
Why does version 1 call the default constructor?
Members are initialized before the construct body runs. A much simpler example to see the same:
#include <iostream>
struct foo {
foo(int) { std::cout << "ctr\n";}
foo() { std::cout << "default ctr\n";}
void operator=(const foo&) { std::cout << "assignment\n"; }
};
struct bar {
foo f;
bar(int) : f(1) {}
bar() {
f = foo();
}
};
int main() {
bar b;
std::cout << "---------\n";
bar c(1);
}
Output:
default ctr
default ctr
assignment
---------
ctr
You cannot initialize a member in the body of the constructor! If you do not provide an initializer, either in the member initializer list or as an in class initializer, then f is default constructed. In the constructor body you can only assign to an already initialized member.

move semantics and copy-elision

I know has been asked several times, I read several tutorial about it but still I can't figure out an answer.
Let's have the typical class
class Foo
{
public:
Foo() : i_(0) { std::cout << "Foo Empty ctor" << std::endl; }
Foo(const Foo& foo) : i_(foo.i_) { std::cout << "Foo Copy ctor" << std::endl; }
Foo(int i) : i_(i) { std::cout << "Foo Param ctor" << std::endl; }
Foo(Foo&& foo) : i_(foo.i_) { foo.i_ = 0; std::cout << "Foo Move ctor" << std::endl; }
Foo(const Foo&& foo) : i_(foo.i_) { std::cout << "Foo const Move ctor" << std::endl; }
~Foo() { std::cout << "Foo " << i_ << " destroyed\n"; }
Foo& operator=(Foo&& other)
{
i_ = std::move(other.i_);
std::cout << "Foo Move assigned\n";
return *this;
}
private:
int i_;
};
Foo getFoo()
{
return Foo(99);
}
int main()
{
Foo f1;
Foo f2(5);
Foo f3(f2);
Foo f4(Foo(4));
Foo f5(std::move(Foo(6));
Foo f6 = getFoo();
Foo f7 = Foo(1);
}
Output
// f1
Foo Empty ctor
// f2
Foo Param ctor
// f3
Foo Copy ctor
// f4 - copy elision
Foo Param ctor
// f5
Foo Param ctor
Foo Move ctor
// f6 - copy elision
Foo Param ctor
// f7 - copy elision
Foo Param ctor
So, except when I call explicitly the move operator, the copy elision optimization do the same work even if do not declare move semantics.
1 - In case when we are not dealing with pointers and I'm not going to call an explicit std::move (so I suppose an implicit call like in the examples) does it have sense declaring move semantics if the copy elision do the same without is?
2 - Does have generally sense declaring move semantics for small classes with simple data? Does it have real advantages?

Empty default constructor, copy constructor and copy assignment: Why with a singleton the member variables are not random?

I am studying constructor, copy constructors and copy assignment a while and I read a fair amount of contents mainly from here as In which situations is the C++ copy constructor called? and What is The Rule of Three? and others, but I still no deeply understanding their exactly behavior. I am performing some tests with the class Boo and Foo bellow and their results are not the ones that I was expecting. In the class Boo I explictly declared its default constructor, copy constructor and copy assingment, and I defined them to do nothing. From this I was expecting that the objects from this class would have member variables with random values, what was indeed observed. Nevertheless, this behavior was not seen with the objects from the class Foo. The only difference between these classes are that the later is a singleton, but its default constructor, copy constructor and copy assignment still explicit declared and defined to do nothing. From this I state my question: Why the values of the member variables of objects from class Foo are not randomly initialized, but always has de same value of "0" and " "?
#include <iostream>
class Boo {
private:
int x;
char y;
public:
int getInt() { return x; }
char getChar() { return y; }
Boo () { std::cout << "Boo default constructor\n"; }
Boo ( const Boo& other ) { std::cout << "Boo copy constructor\n"; }
Boo& operator= ( const Boo& other) { std::cout << "Boo copy assinment\n";
return *this;}
};
class Foo {
private:
int x;
char y;
static Foo *instance;
protected:
Foo() { std::cout << "Foo default constructor\n"; }
Foo ( const Foo& other ) { std::cout << "Foo copy constructor\n"; }
Foo& operator=( const Foo& other) { std::cout << "Foo copy assignment\n"; }
public:
static Foo & uniqueInst();
int getInt() { return x; }
char getChar() { return y; }
};
Foo *Foo::instance = 0;
Foo & Foo::uniqueInst(){
if(!instance) instance = new Foo();
return *instance;
};
int main(){
Boo b1; // default constructor
Boo b2; // default constructor
Boo b3 = b1; // copy constructor
b2 = b1;
std::cout << b1.getInt() << std::endl; // Random values since the constructor does nothing
std::cout << b1.getChar() << std::endl;
std::cout << b2.getInt() << std::endl; // Random values since the copy assignment does nothing
std::cout << b2.getChar() << std::endl;
std::cout << b3.getInt() << std::endl; // Random values since the copy constructor does nothing
std::cout << b3.getChar() << std::endl;
Foo *foo;
foo = &Foo::uniqueInst(); // defaulf construtor
std::cout << foo << std::endl;
std::cout << foo->getInt() << std::endl; // Why not random values?
std::cout << foo->getChar() << std::endl;
};

why does c++ generate a constructor in the following case?

I have a class A
struct A{
A(){}
A(int x): d(x) {}
A(const A& a): d(a.d) {
std::cout << "copy construction" << std::endl;
}
A(A&& a): d(a.d){
std::cout << "move construction" << std::endl;
}
A& operator=(const A& a){
std::cout << "copy assignment" << std::endl;
d = a.d;
return *this;
}
A& operator=(A&& a){
std::cout << "move assignment" << std::endl;
d = a.d;
return *this;
}
int d;
};
and a function func
A func(){
return A(3);
}
if I do this
A x;
x = func();
the output is "move assignment" as expected
but if I construct A like this
A x = func();
then nothing is printed as if c++ generates its own move constructor and refuses to use the defined one.
I'm using visual studio 14
I'd really like to understand this.
Thank you for explanations.
The constructor call is elided.
With gcc, you can disable it with -fno-elide-constructors.
msvc doesn't have equivalent option.

is pointed static_cast valid to avoid copying?

update:
class foo {
public:
foo() : x_(0) { std::cout << "foo constructor\n"; }
foo(foo& c) : x_(c.x_) { std::cout << "foo copy- constructor\n"; }
foo& operator=(foo const& c) {
std::cout << "foo operator=\n";
x_ = c.x_;
return *this;
}
protected:
int x_;
};
class bar : public foo {
public:
bar(int x) { foo::x_ = x; std::cout << "bar constructor\n"; }
bar(bar& c) { std::cout << "bar copy- constructor\n"; }
bar& operator=(bar const& c) {
foo::operator=(c);
std::cout << "bar operator=\n";
return *this;
}
};
int main() {
foo f;
bar b(123);
std::cout << "f = *static_cast<foo*>(&b);\n";
f = *static_cast<foo*>(&b); // no copy constructor is called
std::cout << "f = static_cast<foo>(b);\n";
f = static_cast<foo>(b); // copy constructor and assignment is called
}
output:
g++ -std=c++11 -Wall -pedantic -o main main.cpp && ./main
foo constructor
foo constructor
bar constructor
f = *static_cast<foo*>(&b);
foo operator=
f = static_cast<foo>(b);
foo copy- constructor
foo operator=
Is there an disatvantage of doing the static_cast like *static_cast<foo*>(&b); which is not calling the copy constructor as you can see in the output. see working example here.
In the now completely different question:
f = *static_cast<foo*>(&b);
is equivalent to
f = b;
which calls foo& operator=(foo const& c) with no additional temporaries. However,
f = static_cast<foo>(b);
is equivalent to:
f = foo(b);
or
{
foo temporary(b); // calls foo(foo const& );
f = temporary; // calls foo& operator=(foo const& );
}
which does create a temporary. Definitely prefer to do just:
f = b;
Given the now-functioning code, this line:
base b = *static_cast<base*>(&d);
Is exactly equivalent to these two:
base b = static_cast<b&>(d);
base b = d;
In every case, we're calling base(base const&) with no temporary copies. d is just taken as a const base&.
There is a downside of doing this construction (outside of static_cast just adding noise), which is that b is just a base object. It is not of type derived. So if you had some virtual function base::foo that derived provided an override of, b.foo() would call base::foo. This is known as slicing. If you want to mantain the derived-ness through the assignment, you have to keep a reference or pointer:
base& b = d;
base* b = &d;
Is there an disatvantage of doing the static_cast like *static_cast<foo*>(&b);
Yes. It's unnecessary noise. Just do this:
f = b;
It has the exact same effect.