Why the move constructor isn't invoked? [duplicate] - c++

This question already has answers here:
Copy/Move Constructor is not called when storing result of overloaded operator+
(1 answer)
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)
Is there is a difference between two constructs
(1 answer)
Closed 7 months ago.
I defined a class with both copy and move constructors. The copy constructor seems to work fine but when I try to invoke the move constructor it doesn't work.
#include <iostream>
class A{
public:
A() = default;
A(A& a){
std::cout << "Copy constructor." << std::endl;
};
A(A&& a){
std::cout << "Move constructor." << std::endl;
};
};
int main(int argc, char *argv[]){
auto a = A(A());
std::cout << "here" << std::endl;
auto b = A(a);
return 0;
}
I expect the auto a = A(A()); should invoke move constructor because its input (A()) is an rvalue. But the output is this:
[amirreza#localhost tmp]$ ./a.out
here
Copy constructor.
Is my assumption wrong?
I'm using gcc version 10.3.1 without explicitly specifying the c++ version.

Related

Why can't a copy constructor be templated? [duplicate]

This question already has answers here:
Copy constructor of template class
(2 answers)
What is a converting constructor in C++ ? What is it for?
(3 answers)
Closed 1 year ago.
I am doing a course C++ Fundamentals for Professionals on educative.io website, it mentioned the above statement added in the question,
I created a small c++ program to experiment the same -
#include<iostream>
using namespace std;
template<typename T1>
class MyTemplateClass
{
public:
T1 data;
MyTemplateClass()
{
cout << "in default const" << endl;
}
MyTemplateClass(const MyTemplateClass& other)
{
cout << "in default copy const - created automatically" << endl;
this->data = other.data;
}
template<typename T>
MyTemplateClass(const MyTemplateClass<T>& other)
{
cout << "in templated copy const" << endl;
this->data = other.data;
}
};
int main()
{
cout << "hello world" << endl;
MyTemplateClass<int> obj;
MyTemplateClass<double> obj2(obj);
MyTemplateClass<int> obj3(obj);
}
For obj3 it calls the default copy constructor which makes sense but for obj2 it calls the templated copy constructor, so I see a use for the constructor that if I have a class that takes T1 = double, we can created an object for it from an object of a class that takes T1 = int.
Does obj2 using template MyTemplateClass(const MyTemplateClass& other) - this function doesn't seem like a valid copy constructor according to the rules of a copy constructor defined in c++ but why is it such a case - since this seems like a valid use case?
A constructor template doesn't count as copy constructor even if it has the correct signature of a copy constructor for some template argument.
This is important because if there is no copy constructor declared by the user, then the compiler will declare an implicit one.
So for example
struct A {
A() {}
template<typename T>
A(const T&) { std::cout << "Template called!"; }
};
int main() {
A a;
A b = a;
}
will not output Template called!. Instead of the template specialization the implicitly declared copy constructor (which does nothing in this case) is called.

what function were called when initiate a string with both char array and = operator [duplicate]

This question already has answers here:
Why copy constructor is not called in this case?
(4 answers)
Closed 3 years ago.
According to the explanation in C++ primer 5th.
Initiate a string with char array and using =
operator. It will actually do below two things:
1: Call constructor which accept a const char * to create a temporary string object.
2: Call copy constructor to initiate the true variable;
chapter 13.1 page 618
string null_book = "9-999-99999-9"; // copy initialization
I made a test. and it seems that when I initiate A object with a cahr array.
copy construtor have never been called.
#include <iostream>
int b =5;
using namespace std;
class A
{
public:
A(const char * ch) :chr(*ch) {cout << "contruct ";};
A(const A & a) : chr(0) {cout << "copy_construc ";::b = 2;} ;
A &operator=(const A & a) {cout << "assignment"; return *this;};
char chr;
};
int main() {
A a = "qweqeasd";
cout << b;
cout << a.chr;
A c = A("wrwsx");
cout << b;
cout << c.chr;
}
output:
contruct 5qcontruct 5w
What you have here is called copy-initialization.
A a = "qweqeasd";
If T is a class type and the cv-unqualified version of the type of other is T or a class derived from T, the non-explicit constructors of T are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.
Here the best match is the constructor A(const char * ch) and that is why the output starts with contruct .

Understanding copying objects [duplicate]

This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 7 years ago.
I wrote this:
#include <iostream>
struct A
{
int a;
int b;
A() : a(10) { std::cout << "default ctor" << std::endl;}
~A(){ }
A(const A&){ std::cout << "copy ctor" << std::endl; }
A(const A&&){ std::cout << "move ctor" << std::endl; }
};
A init()
{
A a;
a.b = 20;
return a;
}
int main()
{
A a = init();
std::cout << a.b << std::endl;
}
I expected that A a = init() imposes the move-contructor call, but the outpur is:
default ctor
20
DEMO
The line
A a = init();
is inlined by NRVO. It creates an object by using it's default constructor in its segment of code:
A a;
Your move constructor will not be used here.
The move constructor here can be used with -fno-elide-constructors compiler flag. I've modified your example to compile it with this flag. But note, that default constructor will always be called because NRVO does not affect this in your code. NRVO only means that the object will be constructed in the storage that it is needed (not on the stack of your init method) so it would not be moved or copied. With the no-elide flag it can't be created there so it would be copied/moved there.

Understanding copy constructor in C++ [duplicate]

This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 7 years ago.
I am trying to understand the concept of copy constructors in C++. I have written the following program:
#include<iostream>
using namespace std;
class Box{
private:
int d;
public:
Box(int i){
cout << "Constructor" << endl;
d = i;
}
Box(const Box &old){
cout << "Copy Constructor" << endl;
d = old.d;
}
int getd(){
return d;
}
~Box(){
cout << "Destructor" << endl;
}
Box operator+(const Box& op){
Box c(15);
c.d = d + op.d;
return c;
}
};
int main(){
Box a(10);
Box b = a;
Box c = a+b;
cout << c.getd() << endl;
return 0;
}
The output of this program is as follows:
Constructor
Copy Constructor
Constructor
20
Destructor
Destructor
Destructor
I don't understand why the copy constructor isn't getting called for the third line in the main function. I think that there should be a call to the copy constructor as operator+ function returns by value.
The compiler is optimising out the copy constructor call here, because the standard explicitly allows that copy to be "elided". What would be the point in such a copy, really?
You're absolutely right though, in that it's an opportunity for invocation of the copy constructor, and the compiler could do it. In fact, the standard does require that invoking the copy constructor be valid here.

constructor and copy constructor behaviour in c++ [duplicate]

This question already has answers here:
Why copy constructor is not called here?
(2 answers)
Closed 8 years ago.
I have the following code:
#include <iostream>
using namespace std;
class X
{
public:
int g;
X() { cout << "constr" << endl; }
X(const X& ref1) { cout << "copy constr" << endl; }
};
X f()
{
X ee;
ee.g = 1;
return ee;
}
int main()
{
X ff = f();
return 0;
}
Running the code I see that the constructor was called only once and the copy constructor was never called. Don't you expect two constructor and one copy constructor calls here? Thanks!
This is a special case of the copy elision called return value optimization (the link explains precisely your case).
Copy Elision is an optimization implemented by many compilers to prevent extra, unnecessary, copies. Makes the return-by-value or pass-by-value possible in practice.
Take a look at the example in the following answer: https://stackoverflow.com/a/12953129/1938163
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
(http://en.wikipedia.org/wiki/Return_value_optimization#Summary)
Perhaps incredible to believe the first time, depending on the compiler & settings, the following outputs are all valid:
Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!
In your case, this is a special copy elision optimization called RVO - Return Value Optimization where an object returned by value from a method has its copy elided.