class test{
public:
int data;
test(const test& ){cout<<"INSIDE COPY CON "<<endl;}
test(int val = 0) : data(val){ cout<<"INSIDE CON "<<endl; }
test testfun(const test& obj)
{
cout<<"data : "<<data<<endl;
//test test3(this->data + obj.data);
//cout<<"test3 :"<<test3.data<<endl;
//return test3; //This will work only if return type is changed to const ref
return test(data + obj.data);
}
};
int main()
{
test testO1(1);
test testO2(2);
test testO3 = testO1.testfun(testO2);
cout<<testO3.data<<endl;
getchar();
}
输出:
INSIDE CON
INSIDE CON
data : 1
INSIDE CON
3
在return语句中调用构造函数时会发生什么?因为我能够按价值返回并且它起作用我认为它不是临时位置。或者它是将对象创建为临时对象并使用复制构造函数来复制值,这就是为什么复制构造函数中的打印没有被打印的情况。
答案 0 :(得分:10)
它创建一个临时对象,然后将其复制到返回值。
但是为了提高效率,C ++允许对复制构造函数(或C ++ 11中的移动构造函数)的调用 elided ,因此您不应该依赖于复制构造函数的副作用。
答案 1 :(得分:4)
你提出了一个深刻的问题。
由编译器和相关工具链决定要做什么,但基本模式如下。在调用testfun()
之前,调用者[main()
(在您的示例中)为堆栈上的test03
保留空间。然后,它会将test03
的地址传递给testfun()
。
函数testfun()
必须以某种方式将test
对象放在调用者提供的地址处。如果函数只有一个return语句,可以使用调用者提供的存储来构建返回值。它不需要使用自己的存储。它可以使用main()
。
现在,这种策略并不总是有效。当像testfun()
这样的函数有两个不同的return语句时,它通常会失败,其中一个或两个返回语句不是临时对象而是返回命名对象。在这种情况下,编译器被迫执行否则不必要的复制返回。但是,更常见的情况类似于你的情况,其中testfun()
只是直接在main()
想要它的地方建立返回值。在这种情况下,不会发生实际复制。
因此,在这样的情况下,由编译器决定是否在返回时调用复制构造函数。
答案 2 :(得分:0)
我告诉你return
一个构造函数时发生了什么,让我们为你做一个很好的例子。我引用了一个名为Counter
的类,它以两种方式返回:
按临时对象返回:
// method 1
class Counter
{
private :
int count;
public :
Counter() : count(0) {}
int get_count(void);
Counter operator++(int);
};
int Counter::get_count()
{
return count;
}
Counter Counter::operator++(int)
{
count++;
// create a temp object and assigning count value, then return.
Counter temp;
temp.count = count;
return temp;
}
通过无名临时对象返回:
// method 2
class Counter
{
private :
int count;
public :
Counter() : count(0) {}
Counter(int c) : count(c) {}
int get_count(void);
Counter operator++(int);
};
int Counter::get_count()
{
return count;
}
Counter Counter::operator++(int)
{
count++;
// call 'Counter(int c)' constructor
return Counter(count);
}
主要:
#include <iostream>
using namespace std;
int main()
{
Counter c1, c2;
c1++;
c1++;
c2 = c1++;
cout << "c1=" << c1.get_count() << endl;
cout << "c2=" << c2.get_count() << endl;
return 0;
}
两种方法的输出相同,第二return Counter(count);
中的class
语句执行第一个中所有三个语句所做的操作。这个语句创建了一个Counter
类型的对象,这个对象没有名字;它不会长到足以需要一个。这个未命名的对象初始化为参数count
提供的值,一旦未命名的对象初始化为count
的值,就可以返回它。
第一个class
的效果与第二个class
的效果相同:
输出:
c1= 3
c2= 3
通知,在c2 = c1++;
声明中c1
增加,然后分配到c2
。