为什么返回堆上变量的指针而不是C+中的变量本身+; 我是来自java,现在正在学习C++,

为什么返回堆上变量的指针而不是C+中的变量本身+; 我是来自java,现在正在学习C++,,c++,pointers,heap-memory,stack-memory,C++,Pointers,Heap Memory,Stack Memory,我了解指针是如何工作的,堆栈和堆内存是什么,我在谷歌上搜索了很多,但我似乎不明白为什么我们不返回对象本身,而不是指向堆上创建的对象的指针,如本例所示: (我理解为什么在第一个示例中必须在堆上而不是堆栈上分配对象。) 因此,来自Java,我会这样做: class Thingy; Thingy foo() { Thingy a; return a; } 由于我几乎总是知道堆上的对象比堆栈上的对象寿命长的原因,如果我的函数也能工作,我不明白为什么我们会像第一个示例那样编写函数。指针示例返回

我了解指针是如何工作的,堆栈和堆内存是什么,我在谷歌上搜索了很多,但我似乎不明白为什么我们不返回对象本身,而不是指向堆上创建的对象的指针,如本例所示:

(我理解为什么在第一个示例中必须在堆上而不是堆栈上分配对象。)

因此,来自Java,我会这样做:

class Thingy;

Thingy foo()
{
  Thingy a;
  return a;
}

由于我几乎总是知道堆上的对象比堆栈上的对象寿命长的原因,如果我的函数也能工作,我不明白为什么我们会像第一个示例那样编写函数。

指针示例返回指向对象的指针。它是在堆上分配的,调用方可以直接访问同一副本。调用方还负责在某个时刻从堆中删除Thingy

对象实例示例在堆栈上构造一个Thingy,然后将其复制到调用方的Thingy,假设您有一行Thingy2=Thingy1.foo()调用该函数。与使用一个对象相比,根据对象的大小会有性能损失


使用std::shared_ptr可能更像您习惯的Java。它将创建对象的一个副本,并在对象不再被引用时将其丢弃。您可以将其传递给其他人,并且每个引用都指向对象的同一副本。

您的两个示例并不等价:

在Java示例中,您忘记实际创建对象。
更正代码:

classthingy;
ThingyFoo(){
Thingy a=新的Thingy();
返回a;
}
它们之间还有一个额外的语义差异:
虽然C++支持垃圾回收,但它非常罕见,而在java中则是强制性的。

因此,在C++中,有两个更好的选项:

  • 如果复制或移动成本较低,则按值返回:

    class Thingy;
    Thingy foo() {
        Thingy t; // Thingy t(); would declare a function instead.
        return t; // The copy/move will probably be elided due to NRVO
    }
    
  • 使用
    std::unique_ptr
    返回,以明确表示所有权转移并确保异常安全:

    #include <memory>
    class Thingy;
    std::unique_ptr<Thingy> foo() {
        unique_ptr<Thingy> p = new Thingy();
        return p;
    }
    

  • 如果变量太大,无法放在堆栈上,您没有选择(例如,当您需要一个非常大的数组时),返回值是合理的,但并不总是建议这样做。那么什么是更好的编程实践呢?什么时候不建议只返回值?还有,如果涉及所有权转移,建议返回
    std::unique\u ptr
    而不是原始指针。java语言和AM现在学习C++,< /代码>我知道别人已经评论过,但是一般不使用java作为C++代码编写的模型。否则,你会让自己陷入束缚,创建“奇怪的”C++代码,如果不是完全错误代码。假设Java从未存在过,那么您正在学习一种新的语言。是的,你可以从java应用程序中提取出一个算法或算法,比如代码,并将其转换成C++,但这将是它的范围。<代码> thigy T-();代码>这不是这里最烦人的解析?我试着不写这个:
    Thingy a=newthingy()
    因为这会再次在堆上创建对象,不是吗?@Styxs:在Java中,它会。在C++中,它将在堆上创建对象,然后尝试在指向第一个指针的堆栈上构建另一个对象。这可能会导致编译失败,因为很少有类有理由接受指向构造函数中该类型对象的指针。@重复数据消除程序:那么,我现在应该在堆上还是在堆栈上创建该对象,当我想像以前那样返回它时?如果我想保存performance,我应该返回一个指向堆上对象的指针,对吗?(忽略
    std::unique_ptr
    )@Styxs我不确定您的类是否可复制/可移动,成本是多少。另外,我不知道您是否有其他理由返回指针。一般来说,尽量远离指针。如果必须使用指针,请远离原始指针,因为有更适合的智能指针。
    #include <memory>
    class Thingy;
    std::unique_ptr<Thingy> foo() {
        unique_ptr<Thingy> p = new Thingy();
        return p;
    }
    
    #include <memory>
    class Thingy;
    std::shared_ptr<Thingy> foo() {
        auto p = std::make_shared<Thingy>();
        return p;
    }