当前位置: 首页 > 知识库问答 >
问题:

按值返回不会创建新对象[重复]

鲁博瀚
2023-03-14

我想尝试一下我在C中读到的关于按值返回的内容(在新对象为create的情况下,这与按值传递相同)

#include <iostream>

using namespace std;

class Kar{

public:
    int n;
    static int no;

    Kar(){
        n = ++Kar::no;
        cout << "Creating Kar " << n << endl;
    }

    Kar(Kar &k){
        n = ++Kar::no;
        cout << "Copying Kar " <<k.n<< " to new Kar " << n << endl;
    }

    ~Kar(){
        cout << "Destroying Kar "<< n << endl;
    }

    Kar& operator= (const Kar &k);
};


Kar& Kar::operator= (const Kar &k){

    cout << "Assigning Kar "<< k.n <<" to Kar "<< this->n << endl;
    return *this;
}



int Kar::no;

Kar foo(){
    cout << "Starting foo()" << endl;
    Kar k;
    cout << "Finishing foo()" << endl;
    return k;
}


int main(int argc, char **argv) {
    cout << "Starting!" << endl;

    Kar k;
    k=foo();
    //     Kar k2 = foo();

    cout << "Finishing!" << endl;
    return 0;
}

终端输出是这样的:

Starting!
Creating Kar 1
Starting foo()
Creating Kar 2
Finishing foo()
Assigning Kar 2 to Kar 1
Destroying Kar 2
Finishing!
Destroying Kar 1

>

  • 我希望foo()中的行为是:a.创建Kar2 b。将其复制到Kar 3并返回它(随后将Kar 3分配给Kar 1)。为什么不呢?

    如果我取消注释< code > Kar k2 = foo();我得到编译器消息:

    错误:没有匹配函数调用Kar::Kar(Kar)

    当然,我不能添加构造函数Kar(Kar k){ },因为这是无效的。这是什么意思?为什么不是构造器Kar(Kar


  • 共有2个答案

    蒙勇
    2023-03-14
    匿名用户

    编译器最有可能使用一种称为复制省略的优化,这种优化用于尽可能避免不必要的对象复制。这在通过值返回对象时很常见。在您的例子中,< code>foo()不需要保留它的< code>Kar实例,因为它在< code>return语句后立即被销毁;在< code>foo()返回之前,< code>main()不会对其< code>Kar()实例进行操作。因此,对两者使用一个实例是安全的。

    您可以阅读有关此问题的更多信息:什么是复制省略和返回值优化?

    编辑:一开始没有发现你的第二个问题。复制构造函数应始终采用常量引用参数,即const Kar

    宿景曜
    2023-03-14

    您看到的行为称为返回值优化。因此,编译器不会为返回值创建临时对象,而是消除该对象,并使用在 return 语句之后已创建的对象

    关于你的第二个问题,你会得到一个编译器错误,因为你不能将非常数临时变量(r值)绑定到l值引用(顺便说一句,MSVC接受这一点,但这是非标准行为)。尝试将您的复制构造函数更改为:

    卡尔(康斯特卡尔)

     类似资料:
    • 我正在阅读格式的JSON: 我将“student”存储到一个字符串中,并将每个学生的详细信息——“roll,name,subjects”存储到POJO中。 > ObjectMapper mapper=new ObjectMapper(); Map 返回某个学生的所有主修和辅修课程的最佳方式是什么?我应该做一个hashmap还是列表?或者还有别的办法吗?

    • 问题内容: 例如: 相对于: 一个比另一个更有效吗? 问题答案: 返回之前分配给临时变量使您有机会从newPerson()中进行错误检查和更正。返回新的调用要求newPerson()方法的调用者捕获错误并从错误中恢复。

    • 问题内容: 我试图比较两个相同类型的对象(在dosHave方法中),但是我从未返回过“ true”。这是我的代码: “ Osoba”类如下所示: 来自主代码: 无论我要使用什么输入,这部分都永远不会发生。“ kartoteka”是我当然进口的包裹。每个类都在单独的程序包中,但是使用它们没有问题。我已经尝试了一段时间,但没有任何帮助,似乎 从来都不是真的,但我不知道为什么。没有Boolean.TRU

    • 我想使用Drools规则进行一些验证: 我第一次创建了一个Statefull-KieSession,它第一次按预期工作。然而,当我重新运行该规则时,验证事实仍在内存中,这不是我想要的。因此,我尝试将示例调整为无状态KieSession。 使用KieSession K会话: 使用无状态KieSession会话: statefull会话在validations集合中返回一个Validation对象,无

    • 在我的应用程序中,用户可以将电影标题添加到他们的观看列表中。在我的组件中,我有以下功能: 这目前有一些虚拟信息。 在我的服务中,我有: 所以我将电影对象和令牌传递给后端。 在我的电影ontroller.java我有: 以及movieService中的createMovie功能: 这一切都很好,但我想在电影成功添加到列表(数据库)时向angular应用程序返回一条消息。我想我应该使用@Respons

    • 情况:JDesktopPane中有供应商_JinternalFrame。JDesktopPane中的call SetVisible(true)有一个Supplier_按钮,用于显示供应商框架。但当我通过Dispose()关闭供应商框架时;再次单击按钮后,它将隐藏并不再显示。有两个选项可以使用setshow();和setHide()而不是setDispose()。但我想重新创建Jinternalfr