为什么在C ++中返回指向堆上变量的指针而不是变量本身

时间:2015-01-26 18:49:45

标签: c++ pointers stack heap

所以我来自Java,现在正在学习C ++,

我理解指针是如何工作的,堆栈和堆内存是什么,我已经google了很多但我似乎无法理解为什么我们不会返回对象本身而不是指向创建的对象的指针在堆上就像在这个例子中:

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

class Thingy;

Thingy* foo() 
{
  Thingy *pointerToHeap = new Thingy();
  return pointerToHeap;
}

所以来自Java我会这样做:

class Thingy;

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

因为我几乎总是得到堆上的对象比堆栈中的对象长寿的原因我不明白为什么如果我的函数也能正常工作,我们会编写像第一个例子那样的函数。

2 个答案:

答案 0 :(得分:6)

您的两个例子是不等同

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

class Thingy;

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

Java指针和C ++指针的语法不同,因为Java不允许堆栈分配,只允许堆分配,也不允许分配非类型类型。这意味着没有必要区分单级指针,多级指针和非指针变量,因为它们都是单级指针。

它们之间存在额外的语义差异:
虽然C ++ 支持垃圾收集,但它非常罕见,而在Java中它是强制性的。

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

  1. 如果复制或移动很便宜,则返回按值:

    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
    }
    
  2. 使用std::unique_ptr返回,明确表示所有权转让并将其置为例外安全:

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

    如果从您的版本更改,此选项还具有不破坏ABI的优势,几乎适用于所有平台 它打破了API,但这很容易纠正。

    • 另一种方法是返回std::shared_ptr,以允许使用make_shared

      #include <memory>
      class Thingy;
      std::shared_ptr<Thingy> foo() {
          auto p = std::make_shared<Thingy>();
          return p;
      }
      

答案 1 :(得分:2)

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

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

使用std :: shared_ptr可能更像您习惯使用的Java。它会创建一个对象副本,并在不再引用时将其处理掉。你可以传递它,每个引用都是对象的同一副本。