4

我正在学习 C++。我有 C、C#、ObjC 背景。相当高级的语言。

在 C# 或 ObjC 上,作为函数或方法的结果,返回堆分配的对象是微不足道的。因为对象的清理是管理的(按照惯例)。它会在适当的时候被销毁。

但我不知道我应该如何在 C++ 中处理这个问题。

例如,

std::string* makeString()
{
    std::string* str = GetSomeStringFromArbitrarySource ();
    SaveSomewhereElseInternally (str);
    return str;
}
void useString ()
{
    std::string* str = makeString ();

    // Where and how should I cleanup the `str` object?
    // It is not safe `delete str` here because it may be used on another place.
}

当通过许多函数传递时,清理堆分配对象的推荐和常规方法是什么?

我查看了几个智能指针,但它们看起来并没有真正降低复杂性或需要关心的事情。我误解了智能指针吗?

4

5 回答 5

3

我查看了几个智能指针,但它们看起来并没有真正降低复杂性或需要关心的事情。我误解了智能指针吗?

很可能,是的。在 C++ 中,由于您必须自己处理(没有 GC 会为您清理),因此您需要一种方法来跟踪每个对象的使用情况。

您可以手动将 everynew与 a匹配delete,但这有时很困难或不可能,例如在上面的场景中。无法知道该对象是否正在其他地方使用。

智能指针通过为您管理生命周期来解决此问题,因此您无需删除。他们使用各种机制来跟踪对象正在使用的位置,并delete在最后一个完成时调用。

话虽如此,在这种特定情况下根本没有太多理由使用指针。如果您正在使用std::string,则可以按值传递字符串,这永远不会成为问题。

于 2013-02-28T01:49:51.423 回答
2

您误解智能指针的原因很可能与您编写的原因相同:

std::string* makeString()

而不是大多数 C++ 程序员会写的:

std::string makeString()

您需要更好地理解C++ 中的对象生命周期,然后智能指针概念会容易得多。

于 2013-02-28T02:01:21.910 回答
2

您需要确定对象所需的生命周期,然后使用类型系统来强制执行该生命周期。

从您的示例中,当您想要销毁对象时根本不清楚。

在 C++ 中,对象通过值传递是很常见的(因为原始类型在 Java/C#/etc 中),所以除非你需要std::string在不同的代码之间共享,通常的事情就是返回按值(写makeStringstd::string makeString())的字符串。

如果确实需要多个位置引用同一个对象,则应仔细考虑设计,并确定程序的哪个部分可以安全地控制对象的生命周期。在那个地方按值创建对象,然后在别处传递指针和引用。

于 2013-02-28T01:50:22.517 回答
1

您可能误解了智能指针。在 C++ 中,另一种选择是程序员需要跟踪动态分配对象的生命周期和使用情况。这会影响软件的设计,还会导致人为错误的蔓延。当您使用智能指针时,对象的生命周期几乎会为您处理好。

我是在 C++ 的经典风格(没有智能指针)中长大的,所以如果需要,我可以这样编程,但是如果你是从 C++ 开始的,那么智能指针确实是必须的。

于 2013-02-28T02:00:29.847 回答
0

如果您可以使用 C++11,请使用共享指针。这些指针实现了一种机制,一旦它们中的最后一个被销毁,就删除分配的对象。如果您使用的是 C++03,请使用 boost 的 共享指针。如果您不能使用任何一个,请尝试将堆分配包装在您在堆栈上分配的类中,然后将引用传递给周围的那些,同时阅读RAII wiki

于 2013-02-28T01:51:08.843 回答