C++ constructor invocation [duplicate] - c++

This question already has answers here:
How does guaranteed copy elision work?
(2 answers)
What are copy elision and return value optimization?
(5 answers)
Closed 21 days ago.
The following invokes one instance of the constructor followed by the destructor of A (vs. invoking copy or move constructors). Is this an optimization that only one instance of A is created, or is this behavior mandated by the standard?
#include <iostream>
struct A {
A() {
std::cout << "Constructor\n";
}
~A() {
std::cout << "Destructor\n";
}
A (const A&) = delete;
};
int main() {
A a{A{A{A{A{}}}}};
}

Related

When exactly is copy constructor called? [duplicate]

This question already has answers here:
c++: MyClass x(1,2,3) vs MyClass x = MyClass(1,2,3)
(1 answer)
What's the difference between Radio r = Radio("PSR", 100.8) and Radio("PSR", 100.8)?
(1 answer)
Shouldn't there be a copy ctor invocation here? Elision disabled (no named return value optimization)
(1 answer)
Copy/Move Constructor is not called when storing result of overloaded operator+
(1 answer)
Closed 7 months ago.
I have the following code:
#include<iostream>
using namespace std;
class A{
private:
int x;
public:
A(){x=10;}
A(int m){x=m; cout << "int m constructor" << m << endl;}
A(A& a){cout << "copy constructor:"<<a.x<<"\n"; x=a.x;}
A(A&& a){cout <<"move constructor:"<<a.x<<"\n"; x=a.x;}
};
int main(){
A a(100);
A b = a;
A d = A(30);
}
which outputs the following:
int m constructor100
copy constructor:100
int m constructor30
I was expecting it to output
int m constructor100
copy constructor:100
copy constructor:30
because the constructor function (A(30)) is called.
But somehow the compiler optimises it?
Also A d = A(A(30)) also prints int m constructor30.
Is there some compiler optimization happening here?
Your last line A d = A(30) and A d = A(A(30)) is the mandatory copy elision.

Why are templated copy constructors ignored? [duplicate]

This question already has answers here:
Copy constructor of template class
(2 answers)
Why can't I override the default copy constructor and assignment operator with template versions in C++
(2 answers)
Closed 4 years ago.
I think this code should print "hit" but it doesn't. If you comment out line 6 (the template line), it prints "hit."
#include <iostream>
struct test {
test() {}
template<typename = typename std::enable_if<true>::type>
test(test const & other) {
std::cout << "hit";
}
};
int main()
{
test a;
test b(a);
}
The standard explicitly indicates this. What's the rationale?

Given a rvalue, why move ctor is a better match than const copy ctor? [duplicate]

This question already has answers here:
What is copy/move constructor choosing rule in C++? When does move-to-copy fallback happen?
(2 answers)
Closed 4 years ago.
Sample code, C++11, -fno-elide-constructors.
#include <iostream>
#include <string>
using namespace std;
class ClassA
{
int a, b;
public:
ClassA() = default;
ClassA(const ClassA &obj)
{
cout << "copy constructor called" << endl;
}
ClassA(ClassA &&obj) {
cout << "move ctor called" << endl;
}
};
ClassA bar(ClassA &str)
{
return str; //call copy ctor
}
int main()
{
ClassA str;
ClassA foo = bar(str); //call move ctor
return 0;
}
https://wandbox.org/permlink/DyALfRETs2LfWSjc
Why this assignment ClassA foo = bar(str); call move ctor instead of copy ctor? Since both const lvalue reference and rvalue reference can accept rvalue.
const lvalue reference can bind to everything, so if the compiler would favor this over the rvalue reference the move constructor would not be called ever if a copy constructor is provided, and that would defeat the purpose of having both.
The rvalue reference accepting function is a more specialized version of the more generic const lvalue reference accepting one, and the compiler always chooses the most specialized version.

C++ move constructor not called [duplicate]

This question already has answers here:
Why do I have to call move on an rvalue reference?
(2 answers)
Rvalue Reference is Treated as an Lvalue?
(4 answers)
Closed 5 years ago.
In the following (borrowed) example, in my environment the move constructor is never called:
#include <iostream>
class MyClass {
public:
MyClass()
{
std::cout << "default constructor\n";
}
MyClass(MyClass& a)
{
std::cout << "copy constructor\n";
}
MyClass(MyClass&& b)
{
std::cout << "move constructor\n";
}
};
void test(MyClass&& temp)
{
MyClass a(MyClass{}); // calls MOVE constructor as expected
MyClass b(temp); // calls COPY constructor...
}
int main()
{
test(MyClass{});
return 0;
}
My output is:
default constructor
default constructor
copy constructor
I use XCode version 9.1, shouldnt the move constructor be called on rvalue references? What am I missing here?
John.
What am I missing here?
The point is that everything that has a name is lvalue.
It means that named rvalue reference itself is lvalue and temp from:
void test(MyClass&& temp)
is lvalue as well. So move constructor is not called.
If you want a move constructor to be called, use std::move:
void test(MyClass&& temp)
{
// ...
MyClass b(std::move(temp)); // use std::move here
}
By the way,
MyClass(MyClass& a)
{
std::cout << "copy constructor\n";
}
is not a copy constructor because copy constructor has a form of:
MyClass(const MyClass& a) { ... }

Difference between && and no ref in return type [duplicate]

This question already has an answer here:
Difference between "return-by-rvalue-ref" & "return-by-value" when you return using std::move?
(1 answer)
Closed 6 years ago.
Is there a difference in behavior when the return type is explicitly declared rvalue vs no ref? According to the example below, there doesn't seem to be any difference.
#include <iostream>
#include <vector>
using namespace std;
struct A {
A(int x) : x_(x) {}
A(A&&) = default; // VC12 hasn't implemented default move
A(const A&) = delete;
A& operator=(A&&) = default;
A& operator=(const A&) = delete;
vector<int> x_;
};
struct B{
B(int x) : a_(x) {}
A&& foo1() { return move(a_); } // explicitly declared as rvalue
A foo2() { return move(a_); } // no ref
A a_;
};
int main() {
B b1(7);
A a1 = b1.foo1();
B b2(7);
A a2 = b2.foo2();
cout << a1.x_.size() << ' ' << a2.x_.size() << endl;
cout << b1.a_.x_.size() << ' ' << b2.a_.x_.size() << endl;
return 0;
}
This example has been compiled by Ideone's C++14 compiler (not sure of the exact version, I suspect it's gnu 5.1) and VC12 (Visual Studio 2013). The only minor difference is VC12 requires an explicit move implementation.
Edit: A related SO post said that the two function end up doing the same thing. However, "in many cases it allows the compiler to perform copy elision and elide the calls to the move constructor of the returned type, as permitted by paragraph 12.8/31 of the C++11 Standard". "Copy elision allows the compiler to create the return value of the function directly in the object."
Question 1: Copy elision should still happen when move is explicitly called, right?
Question 2:
When move is explicitly called on a lvalue (so a required called), A&& and A means the same behavior. When move is not explicitly called, meaning the compiler performs copy elision, A should be the only return type. Combining the two scenario above, can I conclude that return type A&& is not useful and only adds confusion?
With
A&& foo1() { return move(a_); }
A foo2() { return move(a_); }
foo1 returns a (rvalue) reference.
foo2 construct an object A with the move constructor.