给出了使用C++返回对象的各种方法,每个返回语句的潜在问题是什么

Lea*_*Cpp 4 c++ return return-value-optimization c++11

下面是具有各种返回语句的代码,并且所有代码都运行良好.编译器会抛出fun_ret_obj1的警告

Test.cpp:在函数'myClass&fun_ret_obj1()'中:Test.cpp:45:警告:返回对局部变量'myObj'的引用

但仍然输出似乎很好.是机会吗?以下任何退货声明是否有任何捕获?
解释会非常有用,谢谢

#include <iostream>
 using namespace std;


 class myClass {
 public:
 int a ;
 myClass()
 {
   a = 10;
 }
 };
 myClass& fun_ret_add()
 {
    myClass *ptr = new myClass();
    return *ptr;
 }

 myClass* fun_ret_ptr()
 {
     myClass *ptr = new myClass();
     return ptr ;
 }

 myClass fun_ret_obj()
 {
     myClass myObj;
     return myObj;
 }

 myClass& fun_ret_obj1()
 {
     myClass myObj;
     return myObj;
 }


 int main()
 {
     myClass obj,obj1;
     std::cout <<"In Main \n";

     myClass *a = fun_ret_ptr();
     std::cout<<a->a<<"\n";

     myClass &b = fun_ret_add();
     std::cout<<b.a<<"\n";

     myClass c = fun_ret_obj();
     std::cout<<c.a<<"\n";

     myClass d = fun_ret_obj1();
     std::cout<<d.a<<"\n";

 }
Run Code Online (Sandbox Code Playgroud)

Ric*_*ges 13

第一个是内存泄漏:

myClass& fun_ret_add()
 {
    myClass *ptr = new myClass();
    return *ptr;
 }
Run Code Online (Sandbox Code Playgroud)

第二个返回一个原始指针(邪恶 - 返回一个std :: unique_ptr)

 myClass* fun_ret_ptr()
 {
     myClass *ptr = new myClass();
     return ptr ;
 }
Run Code Online (Sandbox Code Playgroud)

第三个是完美的 - 返回一个副本,几乎总是被省略.在c ++ 17中,它保证被省略.这是有效和安全的.

 myClass fun_ret_obj()
 {
     myClass myObj;
     return myObj;
 }
Run Code Online (Sandbox Code Playgroud)

更新

在c ++ 17中,您可以通过这种方式保证副本的省略:

 myClass fun_ret_obj()
 {
     return myClass{};
 }
Run Code Online (Sandbox Code Playgroud)

更新结束

第四个是未定义的行为.返回对不存在的对象的引用.永远不要这样做.

 myClass& fun_ret_obj1()
 {
     myClass myObj;
     return myObj;
 }
Run Code Online (Sandbox Code Playgroud)

关于内存泄漏

确实,在第一个示例中,如果调用者知道myClass已经分配了以下内容,则可以释放内存new:

auto& x = fun_ret_add();    // a
...
delete std::addressof(x);   // b
Run Code Online (Sandbox Code Playgroud)

这需要:

  1. 调用者知道 fun_ret_add()是根据new实现的.
  2. fun_ret_add()的实现永远不会改变
  3. (a)和(b)之间没有例外

第二个例子是类似的.在这种情况下,至少有一个提示需要删除该对象,但调用者仍然必须知道该对象已被分配new,并且他必须防止异常.

与此形成对比:

std::unique_ptr<myClass> fun_ret_ptr()
{
    return std::make_unique<myClass>();
    // or
    return { new myClass() };
    // or
    return std::unique_ptr<myClass>(new myClass());
}
Run Code Online (Sandbox Code Playgroud)

现在调用者收到一个智能指针.如果主叫方不执行任何操作,但使用该指针,在myClass对象会得到妥善当指针超出范围中删除,并且所有内存将被回收.