Should this code call copy or move constructor - c++

What's the requirements on the following case in the current C++ Standard?
Suppose that we have the following code:
#include <iostream>
struct Foo
{
Foo() { std::cout << "Foo::Foo()" << std::endl; }
Foo(Foo&) { std::cout << "Foo::Foo(Foo&)" << std::endl; }
Foo(Foo&&) { std::cout << "Foo::Foo(Foo&&)" << std::endl; }
~Foo() { std::cout << "Foo::~Foo()" << std::endl; }
};
struct Bar
{
Foo foo;
};
int main()
{
Bar instance{ Foo{} };
}
What should any implementation do here according to the Standard? Does it require both copy and move constructor to exist (not to be deleted)? Which one should it call?

Since Foo{} is a prvalue and you preform copy initialization, the answer depends on what standard revision you are working with.
C++14 requires the move c'tor to be accessible and not deleted. Even though the actual move may and most probably will be elided.
C++17 will directly initialize the member foo, so both copy and move c'tor need not exist or be accessible.
As an aside, if you opt out of copy initialization and do direct initialization, you can delete both the move and copy c'tors in C++14 as well:
#include <iostream>
struct Foo
{
Foo() { std::cout << "Foo::Foo()" << std::endl; }
Foo(Foo&) = delete;
Foo(Foo&&) = delete;
~Foo() { std::cout << "Foo::~Foo()" << std::endl; }
};
struct Bar
{
Foo foo;
};
int main()
{
Bar instance{ {} };
}

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.

Template customization point with default behavior to do nothing

I have a generic code at which point I leave a possibility to modify data.
if (impl_.mode() == implementation_type::manual)
{
const auto steering = custom::customize_steering(impl_, input.steering());
impl_.output_interface()(steering);
return impl_.do_continue(impl_.params().period());
}
By default I want customize_steering to be optimized out.
Now I have it this way:
template<typename ImplT, typename SteeringT>
constexpr std::decay_t<SteeringT> customize_steering(ImplT &, SteeringT &&steering)
{
return std::forward<SteeringT>(steering);
}
Is it the right way to do or is it too convoluted and passing by const reference will do fine?
I decided to check, and I don't get the results I expect.
#include <iostream>
class foo
{
public:
foo() { std::cout << "Constructed" << std::endl; }
foo(const foo &) { std::cout << "Copy constructed" << std::endl; }
foo(foo &&) { std::cout << "Move constructed" << std::endl; }
~foo() { std::cout << "Destroyed" << std::endl; }
};
template<typename T>
std::decay_t<T> do_nothing(T &&t)
{
return std::forward<T>(t);
// return t;
}
int main(int, char **)
{
const auto &fcr = do_nothing(do_nothing(do_nothing(foo())));
const auto fc = do_nothing(fcr);
return 0;
}
The output is (MinGW64):
Constructed
Move constructed
Move constructed
Move constructed
Destroyed
Destroyed
Destroyed
Copy constructed
Destroyed
Destroyed
What I expected:
Without mandatory copy elision: Constructor -> Move constructor.
With mandatory copy elision (C++17): Constructor (for const auto fc).
How can I make it work?

Difference in calling a constructor with delegation, and in another constructor body

lets say I have a class with 2 constructors like so:
class Foo
{
Foo(int x);
Foo();
...
}
I know that I can call one constructor from another like Foo() : Foo(42) {}, but why shouldn't (or should) I do the following:
Foo() {
Foo(42)
}
What is the difference in these cases?
Some suggest to use an "initializer" method, called from any constructor with their respective arguments, but I am puzzled as to what happens in the case above?
Let's put this example:
#include <iostream>
class B
{
private:
int number;
public:
B()
{
B(1);
}
B(int x) : number(x)
{
std::cout << "Constructor: " << x << std::endl;
}
void print(){
std::cout << "Msg: " << number << std::endl;
}
~B(){std::cout << "Destructor: " << number << std::endl;}
};
int main() {
B b;
b.print();
return 0;
}
Output:
Constructor: 1
Destructor: 1
Msg: 1
Destructor: 1
You are destroying a second object! This is strange, what happens if we use pointers...
#include <iostream>
class B
{
private:
int* arr;
public:
B()
{
B(1);
}
B(int x)
{
std::cout << "Constructor: " << x << std::endl;
arr = new int[x];
}
void print(int n){
std::cout << "Msg: " << arr[n] << std::endl;
}
void set(int n,int val){
arr[n] = val;
}
~B()
{
std::cout << "Destructor: " << arr << std::endl;
delete[] arr;
}
};
int main() {
B b;
b.set(0,14);
b.print(0);
return 0;
}
Constructor: 1
Destructor: 0xc45480
Msg: 14
Destructor: 0xc45480
Look up the pointer addr. They are the same, this means:
We are writing in deleted memory.
We are deleting the same memory twice.
These are two serious problems. You shouldn't do that.
Expression Foo(){Foo(42);} constructs anonymous temporary object that gets destroyed immediately without changing the object being constructed anyhow, while from Foo() : Foo(42){} will initialize the object being constructed.
You should not the following:
Foo() {
Foo(42)
}
When you are in the constructor body the member variables have been just constructed. That's why in C++ initialisation list exists.
The above code is semantically wrong! You are not absolutely using
delegating construction. Instead the statement Foo(42) in the body will just create another object without assigning it to any variable (anonymous variable).
You can imagine something like:
Foo() {
Foo another_obj = Foo(42);
}
In order to use delegating constructor, you must call constructor
in the initialisation list.
Foo() : Foo(42) { }

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;
};

Use of placement-new operator and copy constructor instead of assignment operator

I found a problem while using 3rd party code which cannot be altered. I need to make a copy of object member. I can't do this strictly because one of inner members has private assignment operator. The only solution I found is tricky so I want to ask you if you see any red lights that can affect my program.
Here's the simplified code I'm dealing with (remember that I cannot change it!):
#include <iostream>
#include <algorithm>
class MBool
{
public:
MBool() {};
MBool(const MBool& arg) {}
private:
MBool& operator=(const MBool& arg);
};
class InnerContent {
private:
int* pBuffer;
public:
InnerContent() {
pBuffer = new int[20];
std::cout << "InnerContent()" << std::endl;
}
InnerContent(const InnerContent& otherInnerContent) {
pBuffer = new int[20];
std::copy(otherInnerContent.pBuffer, otherInnerContent.pBuffer + 20, pBuffer);
std::cout << "InnerContent(const InnerContent&)" << std::endl;
}
~InnerContent() {
std::cout << "~InnerContent()" << std::endl;
delete [] pBuffer;
pBuffer = nullptr;
}
virtual void someVirtualFunction() {}
};
class Content {
public:
InnerContent innerContent;
int someNumber;
MBool boolVar;
Content() {
std::cout << "Content()" << std::endl;
}
~Content() {
std::cout << "~Content()" << std::endl;
}
Content(const Content& otherContent) :
innerContent(otherContent.innerContent),
someNumber(otherContent.someNumber),
boolVar(otherContent.boolVar)
{
std::cout << "Content(const Content&)" << std::endl;
}
virtual void someVirtualFunction() {}
};
class A {
public:
Content content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
Content content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
And here's what I'm about to do with it (only this code can be modified and extended):
void copyContent(Content& contentFrom, Content& contentTo) {
contentTo.~Content();
new (&contentTo) Content(contentFrom);
};
int main() {
A a;
B b;
// I wish to do this:
//b.content = a.content;
// but Content class has no operator= function implemented
// also I can't use generated assignment operator function because of MBool::operator= is private
// The only work-around I found is this:
std::cout << "--- Before copying" << std::endl;
copyContent(a.content, b.content);
std::cout << "--- After copying" << std::endl;
}
My solution is to call Content destructor manually to free any dynamically allocated memory in Content and its inner classes. Memory on the stack remains untouched so I can reuse it with placement-new operator that calls copy constructor that is present and does exactly what I need. When main function scope ends 'a' object is cleaned up properly.
Code output:
InnerContent()
Content()
A()
InnerContent()
Content()
B()
--- Before copying
~Content()
~InnerContent()
InnerContent(const InnerContent&)
Content(const Content&)
--- After copying
~B()
~Content()
~InnerContent()
~A()
~Content()
~InnerContent()
I don't want to make my own function that copies all the fields because this class can be updated in new version and there may be additional field that I will not copy and most probably no one will remember to fix it.
Question: Do you think this may cause any memory leaks or memory corruption? Do you see any problems that I didn't mention?
Basically the Idea should work. To protect yourself from forgetting to call the destructor, I think, you should wrap the whole think in a kind of smart pointer like class template. In this example it actually does not wrap a pointer, but the content object itself.
template <typename ContentType>
class content_wrapper {
private:
ContentType content_;
public:
content_wrapper() : content_ {} {};
content_wrapper(const content_wrapper& other) :
content_{other.content_} {};
content_wrapper& operator = (const content_wrapper& other) {
content_.~ContentType();
new (&content_) ContentType(other);
return *this;
}
ContentWrapper& operator * () {
return content_;
}
ContentWrapper* operator -> () {
return &content_;
}
};
now you can use it like that:
class A {
public:
content_wrapper<Content> content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
content_wrapper<Content> content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main() {
A a;
B b;
b.content = a.content; // the wrapper will take care.
b.content->someVirtualFunction();
}
Easy to read and you can never forget the destructor call, whenever you want to assign a content object.