【问题标题】:Returning a local object from a function从函数返回本地对象
【发布时间】:2011-02-03 19:18:48
【问题描述】:

这是从函数返回对象的正确方法吗?

Car getCar(string model, int year) {
   Car c(model, year);
   return c;
}

void displayCar(Car &car) {
   cout << car.getModel() << ", " << car.getYear() << endl;
}

displayCar(getCar("Honda", 1999));

我收到一个错误,“获取临时地址”。我应该这样使用吗:

Car &getCar(string model, int year) {
   Car c(model, year);
   return c;
}

【问题讨论】:

    标签: c++ memory function object reference


    【解决方案1】:

    从函数返回局部变量的引用是不安全的。

    所以是的,这是正确的:

    Car getCar(string model, int year) {
       Car c(model, year);
       return c;
    }
    

    【讨论】:

    • 嗯,我需要一个工厂函数之类的东西,它会创建一个对象并将其返回。
    • 许多(大多数?)编译器优化了return Car(model, year),因此不需要进行额外的复制,所以我会去掉显式的局部变量。
    • @Steven:许多(大多数?)编译器也实现了命名返回值优化 (NRVO),因此通常没有区别。
    • @pocoa:您还可以通过分配new 实例并通过指针返回来为所有这些使用动态内存。我建议使用适当类型的智能指针,以避免泄漏。
    • @James:你可能是对的。最后我检查了一下,命名值不太可能被优化。
    【解决方案2】:

    getCar 按值返回Car,这是正确的。

    您不能将该作为临时对象的返回值传递给displayCar,因为displayCar 需要Car&amp;。您不能将临时对象绑定到非常量引用。您应该更改 displayCar 以获取 const 引用:

    void displayCar(const Car& car) { }
    

    或者,您可以将临时变量存储在局部变量中:

    Car c = getCar("Honda", 1999);
    displayCar(c);
    

    但是,最好让displayCar 使用 const 引用,因为它不会修改对象。

    不要返回对本地 Car 变量的引用。

    【讨论】:

    • 您也可以在不调用复制构造函数的情况下存储临时变量(如果您不需要通过 c 进行更改,则通过使用对 const 的引用发生在 Car c = getCar(...) 中:const Car &amp;c = getCar(...)稍后。
    【解决方案3】:

    你的问题是:

    void displayCar(Car &car) {
       cout << car.getModel() << ", " << car.getYear() << endl;
    }
    

    你应该使用 const 引用:

    void displayCar( const Car & car ) {
       cout << car.getModel() << ", " << car.getYear() << endl;
    }
    

    这个函数:

    Car getCar(string model, int year) {
       Car c(model, year);
       return c;
    }
    

    就目前而言是可以的,但它所做的只是构造函数所做的,所以它是多余的。对于这个type函数,传回一个值而不是一个引用是正确的做法,但是,模型参数应该通过const引用传递:

    Car getCar( const string & model, int year) {
    

    一般来说,对于像 string 或 Car 这样的类类型,参数的默认选择应该始终是 const 引用。

    【讨论】:

      【解决方案4】:

      更好:

      Car getCar(string model, int year) { 
            return Car(model, year);  
      }
      

      【讨论】:

      • 正是我在回答中所说的“复制操作”的意思。尽管目前这是标准解决方案,但它比仅返回地址要昂贵得多。
      • @themoondothshine:大多数编译器(据我所知)都会在这里执行 RVO,所以这是一个非常便宜的操作。
      【解决方案5】:

      是的,返回引用或指向临时对象的指针绝对不安全。当它到期时(即,当函数getCar 退出时),您将留下技术上称为“悬空指针”的东西。

      但是,如果您热衷于减少对对象的复制操作,则应该查看 C++0x 的“移动语义”。这是一个相对较新的概念,但我相信它很快就会成为主流。 GCC 4.4 以上支持 C++0x(使用编译器选项-std=c++0x 启用)。

      【讨论】:

        猜你喜欢
        • 2015-07-26
        • 2012-02-29
        • 2021-08-18
        • 2021-08-09
        • 1970-01-01
        • 2016-03-17
        • 1970-01-01
        • 2015-12-15
        • 2020-06-28
        相关资源
        最近更新 更多