返回指针的最佳方法

时间:2012-06-30 15:33:43

标签: c++

我已经看过至少5个以这种方式返回指针的C ++教程网站:

int* somefunction(){
    int x = 5;
    int *result = &x;
    return result;
}

这不是一个非常非常糟糕的主意吗?我的逻辑告诉我,返回指针的值可以随时被覆盖。我宁愿认为这是正确的解决方案:

int* somefuntion(){
    int x = 5;
    int* result = new int;
    *(result) = x;
    return result;
}

然后离开调用函数删除指针。或者我错了吗?

6 个答案:

答案 0 :(得分:8)

你对这个问题的直觉是正确的 - 结果就是UB。但是,您提出的解决方案很糟糕。 “让调用者删除它” hideously 容易出错且不可取。相反,将它返回到某个拥有的类中,该类正确地封装了它的预期用途 - 最好是std::unique_ptr<int>

答案 1 :(得分:6)

是的,第一个选项将返回一个悬空指针,并导致未定义的行为。你的第二个选择是正确的,尽管你可以写:

int* somefuntion(){
    return new int(5);
}

或在方法中包含static变量并返回其地址。

答案 2 :(得分:3)

您的问题将几个不同的问题合并为一个问题。实际上,这里的主要问题是你是否真的需要这种混合物。

没有“返回指针”这样的东西。你没有“返回指针”只是因为你想“返回一个指针”。返回指针是出于某些特定原因而完成的,这个原因将决定它是如何完成的以及需要做什么才能确保它正常工作。

您的原始示例并未真正说明,因为在您的原始示例中,没有任何有意义的理由返回指针。看起来您只需返回int

例如,在许多情况下,您需要返回指针,因为它是指向动态分配对象的指针,即生命周期不受语言范围规则约束的对象。请注意,在这种情况下,随意关系的作用相反:您需要一个动态对象 - &gt;你必须返回一个指针。那样,而不是相反。在你的例子中,你似乎向后使用它:我想返回一个指针 - &gt;我必须动态分配对象。后一种推理存在根本性的缺陷,尽管人们可能会看到它的使用频率超出预期。

如果你真的需要一个动态分配的对象(正如我上面所说,主要原因是覆盖了语言的基于范围的生命周期规则),那么内存所有权问题就成了问题。为了知道何时可以/必须释放此内存以及谁必须解除分配,您必须实现独占(在任何时刻指定一个所有者)或共享(如引用计数)所有权方案。它可以用原始指针完成,但更好的想法是使用库提供的各种智能指针类。

但是在许多情况下你也可以返回指向非动态对象(静态或自动)的指针,假设这些指针的生命周期与它们指向的对象的生命周期相同或更短,这是完全正常的。 / p>

换句话说,决定返回指针的原因在C和C ++之间并没有什么不同。它与设计/意图相关,而不是与语言相关。只有C ++为您提供了更多工具,一旦您决定返回指针,就可以让您的生活更轻松。 (这有时会激励C ++程序员过度使用隐藏指针)。

在任何情况下,这都是您尝试实现的功能问题。一旦你知道了,你就可以做出关于你是否应该“返回指针”的好决定。如果你最终决定返回一个指针,它将帮助你选择正确的返回方法。这就是它的工作原理。试图向后思考它(“我只是想返回一个指针,但我还没有真正的理由”)只会产生学术无用的答案,其中每一个都可能被证明是“错误的”具体情况。

答案 3 :(得分:2)

是的,第一个例子并不好,因为你将返回一个指向内存的指针,系统可能会重新设置其他内容。第二个例子是更好的,但仍然存在泄漏内存的风险,因为某些功能的调用者不清楚它是否有责任删除指向的内存。

这样的事可能会更好:

std::unique_ptr<int> somefunction(){
    int x = 5;
    std::unique_ptr<int> result( new int );
    *result = x;
    return result;
}

这样,unique_ptr将负责删除你新用的内存,并有助于消除潜在的内存泄漏。

答案 4 :(得分:1)

如你所怀疑和其他人澄清的那样,第一种方法显然是错误的。虽然C ++是一种系统语言,并且在某些情况下您可能希望这样做(它会在堆栈上返回特定的相对位置,在大多数系统上),但它几乎没有。第二种方法更加清晰。

但是,在C ++中不应该鼓励任何方法。 C ++的一个要点是你现在有引用和异常,而不仅仅是C的指针。所以你要做的就是返回一个引用,如果内存分配失败,允许new在栈中引发异常。 / p>

答案 5 :(得分:0)

别忘了     删除 调用方法后的指针,这是正确的。