返回指针的最佳方式
Best way of returning a pointer
我见过至少 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;
}
然后离开调用函数以删除指针。还是我错了?
你对问题的直觉是正确的 - UB 就是结果。但是,您提出的解决方案是 le 坏的。"让调用者删除它"非常容易出错,也是不可取的。相反,在某个正确封装其预期用途的拥有类中返回它 - 最好是std::unique_ptr<int>
。
是的,第一个选项将返回一个悬空指针,并导致未定义的行为。您的第二个选项是正确的,尽管您可以只写:
int* somefuntion(){
return new int(5);
}
或者在方法中包含一个static
变量并返回其地址。
是的,第一个示例并不好,因为您将返回一个指向内存的指针,系统可能会将其重新用于其他用途。第二个示例更好,但仍然有泄漏内存的风险,因为某些函数的调用者不清楚他们有责任删除指向的内存。
这样的东西可能会更好:
std::unique_ptr<int> somefunction(){
int x = 5;
std::unique_ptr<int> result( new int );
*result = x;
return result;
}
这样,unique_ptr将负责删除您新建的内存,并有助于消除潜在的内存泄漏。
您的问题将几个不同的问题混合为一个。实际上,这里的主要问题是你是否真的需要这种混合物。
本身没有"返回指针"这样的事情。您不会仅仅因为要"返回指针"而"返回指针"。返回指针是出于某种特定原因而完成的,该原因将指示如何完成以及需要做什么以确保其正常工作。
您的原始示例并没有真正说明这一点,因为在原始示例中,根本没有有意义的理由返回指针。看起来您可以简单地返回一个int
.
例如,在许多情况下,您需要返回一个指针,因为它是指向动态分配对象的指针,即其生存期不受语言范围规则约束的对象。请注意,在这种情况下,偶然关系的作用方向相反:你需要一个动态对象 ->你必须返回一个指针。这样,而不是相反。在您的示例中,您似乎向后使用它:我想返回一个指针 ->我必须动态分配对象。后一种推理从根本上是有缺陷的,尽管人们可能会看到它的使用频率比人们预期的要高。
如果你真的需要一个动态分配的对象(正如我上面所说,主要原因是覆盖语言的基于范围的生存期规则),那么内存所有权的问题就会成为一个问题。为了知道何时可以/必须释放此内存以及谁必须释放它,您必须实现独占(随时指定一个所有者)或共享(如引用计数)所有权方案。它可以使用原始指针来完成,但更好的主意是使用库提供的各种智能指针类。
但在许多情况下,您也可以返回指向非动态对象(静态或自动)的指针,假设这些指针的生存期与它们指向的对象的生存期相同或更短,这是完全可以的。
换句话说,决定返回指针背后的原因在 C 和 C++ 之间并没有真正的区别。它更多地与设计/意图相关,而不是与语言相关。只是C++为您提供了更多工具,一旦您决定返回指针,就可以使您的生活更轻松。(这有时会激励C++程序员过度使用隐藏的指针)。
无论如何,同样,这是您尝试实现什么功能的问题。一旦你知道了这一点,你就可以做出一个关于是否应该"返回指针"的好决定。如果您最终决定返回指针,它将帮助您选择合适的返回方法。这就是它的工作原理。试图倒着想("我只是想返回一个指针,但我还没有真正的理由")只会产生学术上无用的答案,每个答案都可以在某些特定情况下被证明是"错误的"。
正如你怀疑和其他人澄清的那样,第一种方法显然是错误的。 尽管C++是一种系统语言,并且在某些情况下您可能希望这样做(在大多数系统上,它会返回堆栈上的特定相对位置),但它几乎从来都不对。 第二种方法要理智得多。
但是,C++不应鼓励这两种方法。 C++的要点之一是您现在有引用和异常,而不仅仅是 C 的指针。 因此,您要做的是返回一个引用,并允许 new 在内存分配失败时在堆栈上抛出异常。
不要忘记 删除调用方法后的指针,这是正确的。
- 在c代码之间共享数据的最佳方式
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 在reactor中存储eventHandlers的最佳方式是什么
- 在AVX通道中混洗的最佳方式
- 从 T 创建 std::future 的最佳方式<T>
- C++:使用 std::unique_ptr 访问重载运算符++的最佳方式?
- 对列表列表中的元素进行分组的最佳方式
- 利用 GPU 的最佳方式
- 使用 QT C++过滤大数据的最佳方式
- 算法设计:用边界数字表示 2D 网格的最佳方式,以C++?
- 在C++中共享键值对的最佳方式
- 为Catch2中的外部文本文件指定路径的最佳方式
- 代表Quarto棋盘游戏棋子的最佳方式
- 等待线程的最佳方式是什么
- 将uint8_t*buffer和size_tbufferlen从C++传递到C中的API函数的最佳方式是什么
- 创建控制台菜单C++的最佳方式
- 只显示片段着色器的最佳方式是什么
- 复制文件的最佳方式是什么,以便我可以在复制过程中轻松取消复制?