This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are copy elision and return value optimization?
I have the following program:
#include <iostream>
using namespace std;
class Pointt {
public:
int x;
int y;
Pointt() {
x = 0;
y = 0;
cout << "def constructor called" << endl;
}
Pointt(int x, int y) {
this->x = x;
this->y = y;
cout << "constructor called" << endl;
}
Pointt(const Pointt& p) {
this->x = p.x;
this->y = p.y;
cout << "copy const called" << endl;
}
Pointt& operator=(const Pointt& p) {
this->x = p.x;
this->y = p.y;
cout << "op= called" << endl;
return *this;
}
};
Pointt func() {
cout << "func: 1" << endl;
Pointt p(1,2);
cout << "func: 2" << endl;
return p;
}
int main() {
cout << "main:1" << endl;
Pointt k = func();
cout << "main:2" << endl;
cout << k.x << " " << k.y << endl;
return 0;
}
The output I expect is the following:
main:1
func: 1
constructor called
func: 2
copy const called
op= called
main:2
1 2
But I get the following:
main:1
func: 1
constructor called
func: 2
main:2
1 2
The question is: why doesn't returning an object from func to main call my copy constructor?
This is due to Return Value Optimization. This is one of the few instances where C++ is allowed to change program behavior for an optimization.
Related
I have an error in my code, I want to display the sume of 2 objects with pointers in a class. Please help me to fix it, maybe is due to the pointers. Can you see what's wrong?
This is the error:
<source>(79): error C2280: 'Pair &Pair::operator =(const Pair &)': attempting to reference a deleted function
<source>(60): note: compiler has generated 'Pair::operator =' here
<source>(60): note: 'Pair &Pair::operator =(const Pair &)': function was implicitly deleted because 'Pair' has a user-defined move constructor
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Pair {
int *x, *y;
public:
Pair() {
x = new int(sizeof(x));
y = new int(sizeof(y));
*x = 0;
*y = 0;
}
Pair(int a, int b) {
x = new int(sizeof(x));
y = new int(sizeof(y));
*x = a;
*y = b;
}
Pair(Pair& ob) {
x = new int(sizeof(ob.x));
y = new int(sizeof(ob.y));
*x = *(ob.x);
*y = *(ob.y);
}
Pair(Pair&& ob) {
x = new int(sizeof(ob.x));
y = new int(sizeof(ob.y));
*x = *(ob.x);
*y = *(ob.y);
}
Pair(int a):Pair(a, 0) {
}
void setX(int X) {
*x = X;
}
void setY(int Y) {
*y = Y;
}
int* getX() {
return x;
}
int* getY() {
return y;
}
~Pair() {
delete[]x;
delete[]y;
}
Pair sume(Pair ob1){
Pair ob2;
*(ob2.x) = *(ob1.x) + (*x);
*(ob2.y) = *(ob1.y) + (*y);
return ob2;
}
double media() {
return (double(*x) + double(*y)) / 2;
}
};
int main() {
Pair ob1, ob2(5), ob3(4, 3);
ob1.setX(6);
ob1.setY(7);
cout << "X= " << *(ob1.getX())<<endl;
cout << "Y= " << *(ob1.getY())<<endl;
cout << "Media este: " << ob1.media();
cout << "\nX= " << *(ob2.getX()) << endl;
cout << "Y= " << *ob2.getY() << endl;
cout << "Media este: " << ob2.media();
cout << "\nX= " << *(ob3.getX()) << endl;
cout << "Y= " << *(ob3.getY()) << endl;
cout << "Media este: " << ob3.media();
Pair ob4,ob5,ob6;
ob4 = ob1.sume(ob2);//here the compiler shows the error
cout <<"\nX= "<< *(ob4.getX())<<endl;
cout << "Y= " << *(ob4.getY())<<endl;
}
how to overload assignment operator to satisfy ob1=ob2=ob3 (ob1,ob2,ob3 are objects of same class) where we have no concern for (ob2 = ob3) which is similar to (ob2.operator=(ob3)) but we need a parameter of type class when we are assigning this result to ob1 which is similar to (ob1.operator=(ob2.operator=(ob3)) below is the code that gives me error
#include<bits/stdc++.h>
using namespace std;
class A
{
public:
int x;
int *ptr;
A()
{
}
A(int a, int *f)
{
x = a;
ptr = f;
}
void operator=(A&);
};
void A::operator=(A &ob)
{
this->x = ob.x;
*(this->ptr) = *(ob.ptr);
}
int main()
{
int *y = new int(3);
A ob1, ob2, ob3(5, y);
ob1 = ob2 = ob3;
cout << ob1.x << " " << *(ob1.ptr) << endl;
cout << ob2.x << " " << *(ob2.ptr) << endl;
cout << ob3.x << " " << *(ob3.ptr) << endl;
return 0;
}
Your asignement operator should return a reference to *this, and be defined as
A& operator=(const A&);
or, better, pass by value and use the copy-and-swap idiom
A& operator=(A);
For an excellent intro to operator overloading, see this.
I am new to programming. sorry for my bad english.
I have tried to use rvalue as initialiser to initial objects.
So, according to the code, it would print out what are the used constructor and assignment operator.
But turned out object "what2" and "what3", those don't print out anything.
here is the code:
#include <iostream>
using namespace std;
class X{
public:
int x;
X()= default;
X(int num):x{num}{}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
std::cout << x << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2{a+b};
cout << "---------------" << endl;
X what3 = a+b;
cout << "---------------" << endl;
std::cout << what1.x << std::endl;
std::cout << what2.x << std:: endl;
std::cout <<what3.x << std::endl;
return 0;
}
the output is:
---------------
move assignment
---------------
---------------
---------------
18
18
18
Program ended with exit code: 0
only "what1" uses assignment properly.
so, how can i use rvalue to initial an object? and using operator= to initial an object?
thank you very much.
Your code could result in move operations being used, but your compiler has chosen to elide those moves and allocate the return of operator+ directly at the call site. You can see this happening if you disable copy elision in your compiler (-fno-elide-constructors in GCC or Clang).
Your move constructor and assignment operator will be successfully used in contexts in which copy elision is not permitted, such as this:
X what2 { std::move(what1) }; //can't elide copy, move constructor used
The following code triggers more of your constructors/operators, check it out to see which trigger in what cases
#include <iostream>
using namespace std;
class X{
public:
int x;
X()
{
x = 0;
std::cout << "constructor" << std::endl;
}
X(int num):x{num}
{
std::cout << "list initilizer" << std::endl;
}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
cout << "---------------" << endl;
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2(a+b);
cout << "---------------" << endl;
X what3 = X(a);
cout << "---------------" << endl;
X what4 = X();
cout << "---------------" << endl;
X what5 = std::move(what1);
cout << "---------------" << endl;
what5 = std::move(what1);
cout << "---------------" << endl;
what5 = what1;
cout << "---------------" << endl;
return 0;
}
GCC provides the -fno-elide-constructors option to disable copy-elision. if you want to elide the copy-elision then use flag -fno-elide-constructors. Refer https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization/27916892#27916892 for more detail
I cannot understand the order of constructor and destructor calls? What will execute first in this statement A b=f(a)? Can someone please help me out?
#include<iostream>
using namespace std;
class A {
int x;
public:
A(int val = 0)
:x(val) {
cout << "A " << x << endl << flush;
}
A(const A& a) {
x = a.x;
cout << "B " << x << endl << flush;
}
void SetX(int x) {
this->x = x;
}
~A() {
cout << "D " << x << endl << flush;
}
};
A f(A a) {
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
int main()
{
A a(1);
A b=f(a);
b.SetX(-100);
return 0;
}
Output Window:
A 1
B 1
C
B 100
D 100
D -100
D 1
Why does it print B 1 in line 2 of the output window?
"Why does it print B 1 in line 2?"
Because the copy constructor was called from this statement
A b=f(a);
The function f() requires A being passed by value, thus a copy for this parameter is made on the function call stack.
If your next question should be, how you can get over this behavior, and avoid to call the copy constructor, you can simply pass the A instance as a reference to f():
A& f(A& a) {
// ^ ^
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
Side note: endl << flush; is redundant BTW, std::endl includes flushing already.
I was told in this answer to delete the member myValue in the destructor. But if I add it I am getting an exception. From the console messages it seems to be entering the destructor at two moments with the same object(!?)
Note: The code is my attempt to an exercise. In it we are given a code to which we can only add to it. Essentially the content of the main and the constructor without parameters is that is given. The rest is what I am adding to it to make it work.
My guess is that a copy of the object made during some function call is destroying the same myValue after exiting the function call. How is the right way to preserve the data pointed to by two objects in this case?
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyFancyInt
{
public:
// A constructor that inputs a value for initialization, so that line /*1*/ makes sense.
MyFancyInt(int x) : myValue(new int(x))// The part after the : initializes myValue to point to the newly created int with value x.
{
cout << "Constructor that initializes with myValue = " << x << endl;
};
//Destructor.
~MyFancyInt()
{
cout << "A MyFancyInt destroyed that had the myValue = "<< this->myValue<< " pointing to a "<< *(this->myValue) << endl;
//delete myValue;
};
//A 'Copy Constructor', so that line /*3*/ makes sense. Aparently C++ creates default copy constructors.
//A copy constructor input an already existing MyFancyInt, creates a new MyFancyInt and initializes it with the data of the former.
MyFancyInt(MyFancyInt& x)
{
myValue = x.myValue;
};
//The construtor without parameters already given in the exercise.
MyFancyInt()
{
cout << "Default constructor" << endl;
myValue = 0;
}
// Friend function to overload the operator +. This one takes two MyFancyInt. It is not needed. It can be commented out.
friend MyFancyInt operator+(MyFancyInt &x, MyFancyInt &y);
// Friend function to overload the operator +. This one takes an int and a MyFancyInt. It is needed for line /*6*/.
friend MyFancyInt operator+(int x, MyFancyInt &y);
// Friend function to overload the operator +. This one takes a MyFancyInt and an int. It is needed for line /*5*/.
friend MyFancyInt operator+(MyFancyInt &x, int y);
// Friend function to overload the output stream operator <<. It is needed for the printing in line /*7*/.
friend ostream& operator<<(ostream& os, const MyFancyInt& x);
// Overloading the operator =. It is needed for line /*2*/, /*5*/, and /*6*/.
MyFancyInt& operator=(const MyFancyInt &x);
private:
int* myValue;
};
MyFancyInt operator+(MyFancyInt &x, MyFancyInt &y)
{
cout << "MyFancyInt + MyFancyInt = " << x.myValue << " + " << y.myValue << "= " << *(x.myValue) << " + " << *(y.myValue) << endl;
MyFancyInt z=MyFancyInt(*(x.myValue) + *(y.myValue));
cout << "= " << *(z.myValue) << endl;
return z;
};
MyFancyInt operator+(int x, MyFancyInt &y)
{
cout << "int + MyFancyInt = " << x << " + " << y.myValue << " = " << x << " + " << *(y.myValue)<< endl;
MyFancyInt z = MyFancyInt(x + *(y.myValue));
cout << " = " << *(z.myValue) << endl;
return z;
};
MyFancyInt operator+(MyFancyInt &x, int y)
{
cout << "MyFancyInt + int = " << x.myValue << " + " << y << " = " << *(x.myValue) << " + " << y << endl;
MyFancyInt z = MyFancyInt(*(x.myValue) + y);
cout << " = " << *(z.myValue) << endl;
return z;
};
ostream& operator<<(ostream& os, const MyFancyInt& x)
{
os << *(x.myValue);
return os;
}
MyFancyInt& MyFancyInt::operator=(const MyFancyInt &x)
{
cout << "Entering the assigment operator." << endl;
myValue = x.myValue;
return *this;
};
int _tmain(int argc, _TCHAR* argv[])
{
MyFancyInt mfi1(1); /*1*/
MyFancyInt mfi2 = mfi1; /*2*/
MyFancyInt mfi3(mfi1); /*3*/
MyFancyInt mfi4; /*4*/
mfi4 = mfi3 + 2; /*5*/
mfi4 = 3 + mfi3; /*6*/
cout << mfi4 << endl; /*7*/
return 0;
}
The way your copy constructor is written, when you copy an object, both objects will be pointing to the same address and both will try to delete it.