5
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 语句中调用构造函数时会发生什么?由于我能够按价值返回并且它有效,我认为它不是临时位置。还是将对象创建为临时对象并使用复制构造函数来复制值,在这种情况下,为什么复制构造函数中的打印没有被打印出来。

4

3 回答 3

10

它创建一个临时对象,然后将其复制到返回值。

但为了提高效率,C++ 允许省略对复制构造函数(或 C++11 中的移动构造函数)的调用,因此您不应依赖复制构造函数的副作用。

请参阅返回值优化想要速度?按值传递

于 2012-06-08T00:41:09.180 回答
7

你问了一个尖锐的问题。

由编译器和相关的工具链决定做什么,但基本模式如下。在调用之前testfun(),调用者 [ ,在您的示例中] 为堆栈main()保留空间。test03然后它传递test03to的地址testfun()

该函数testfun()必须以某种方式将test对象放在调用者提供的地址处。如果函数只有一个 return 语句,则可以自由使用调用者提供的存储来构建返回值。它不需要使用自己的存储。它可以使用main()'s。

现在,这种策略并不总是奏效。当一个类似的函数有两个不同的返回语句时,它通常会失败testfun(),其中一个或两个返回的不是临时对象而是命名对象。在这种情况下,编译器被迫执行否则不必要的返回时复制。但是,更常见的情况类似于您的情况,其中testfun()只是在需要它的位置直接构建返回值main()。在这种情况下,不会发生实际复制。

因此,在这种情况下,是否在返回时调用复制构造函数由编译器决定。

于 2012-06-08T00:48:12.810 回答
0

我告诉你return构造函数时会发生什么,让我们为你做一个很好的例子。Counter我以两种方式引用一个名为 return 的类:

通过临时对象返回:

// 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

于 2017-03-03T15:58:26.903 回答