c++ - 从 C++ 中的函数返回引用的推荐方法

标签 c++ memory-management memory-leaks

我一直在使用这种方法从 C++ 中的函数返回引用。但是,我怀疑有更好的模式来执行这样的操作。另外,我猜想这种方法意味着内存泄漏。

class A {};
A& return_instance_of_A(){
    A* result = new A();
    return *result;
}

使用 shared_ptr 会是更好的选择吗?

最佳答案

What is the recommended way of returning a reference from a function?

语法上,只返回一个引用。

int& myFunction() { .... }

引用的行为几乎像指针。你的例子虽然有一些问题。

你分配的对象在某个时候需要被删除,通常这是通过指针来处理的。通常,收到您以后需要的引用是非常奇怪的 delete .

在现代 C++ 中,以这种断开连接的方式处理内存分配也不常见。我同意你退回 shared_ptr 的建议.这使得所有权明确,并且不会像您的示例那样无意中泄漏内存。

您的示例不一定会导致内存泄漏,但它很尴尬,因为您对调用者(即,delete 返回的对象)提出了编译器未强制执行的某些要求.


编辑,解决那些建议按值返回的人:这仅取决于调用者的要求。许多小型/实用对象,如 RectangleSize旨在按值传递,这使事情变得非常简单和直观。

一个实际的例子是这样的:

inline Rect make_square_rect(int left, int right, int width)
{
  return Rect(left, right, width, width);
}

肯定像这样的函数最好按值返回。请注意此功能与构造函数有多么相似......

对于其他更大、更 promise 和有状态的对象,如 TcpConnectionWindow ,这种相似性变得更加清晰。所有权和内存管理的问题被放大了。

这同样适用于任何无法复制/移动的内容。

因此,创建一个新的 Window不能像 Rect 那样随意.创建 Rect像你这样的函数并不真正关心所有权问题,因为复制 Rect 是多么便宜和简单。目的。但是如果你的函数返回类似 Window 的东西,那么您的函数自然会解决所有权问题——可能通过返回 shared_ptr<Window> 来解决.


编辑 #2:构造函数性质

为了回应您的评论,我将再次指出这些函数与构造函数非常相似。这些函数实际上应该只是设置一个对象供首次使用 - 但我们坐在这里试图决定函数应该如何处理所有权/复制。

真的,这正是构造函数应该做的。

struct BigInteger
{
    BigInteger(int initial_value) { ... }
};

在这里,构造函数不需要处理我们正在谈论的概念。调用者决定他想如何处理所有权:

BigInteger* ptr = new BigInteger(42);
BigInteger val = BigInteger(42);

作为构造函数编写,这可以处理这两种情况。在我看来,这种情况的烦人之处在于构造函数不能在 C++ 中命名。例如,假设您正在编写这些函数:

BigInteger make_big_integer_by_multiplying(int a, int b) { ... }
BigInteger make_big_integer_by_adding(int a, int b) { ... }

没有好的方法可以将它们变成构造函数。您需要一个符号名称来区分这些函数,而构造函数不能有名称。

作为独立函数编写,您必须决定所有权行为。您必须权衡利弊,主要是:考虑调用者希望如何使用该对象。如果调用者想要一个持久的、有状态的长期存在的对象,那么返回一个 shared_ptr。 .如果调用者将该对象用作中间值类型(我认为 BigInteger 绝对是),则按值返回。

关于c++ - 从 C++ 中的函数返回引用的推荐方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30032020/

相关文章:

python - 优化 numpy 中的内存使用

c - Arduino伺服结构 "does not name a type"

c++ - 有没有办法使用核心文件找到泄漏的内存?

java - 查找谁分配直接内存的有效方法

c++ - 抽象虚函数的 vtable 中有多少条目?

c++ - 将 lparam 作为指向类的指针发送,并在 WndProc() 中使用它

.net - 清理 GC 的 .NET 数据结构

delphi - 从函数返回 OleVariant 会导致对所包含的 IDispatch 对象产生无法释放的额外引用

c++ - 串口未读取完整传输

c++ - 在堆上分配内存的函数原型(prototype) (C/C++)