清理堆分配对象的良好实践或约定
Good practice or convention for cleanup heap allocated object?
我正在学习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.
}
当堆分配的对象传递给许多函数时,推荐和传统的清理方法是什么?
我看了几个智能指针,但它们看起来并不真正减少复杂性或关心的事情。我是不是误解了智能指针?
我看了几个智能指针,但它们看起来并没有真正减少复杂性或关心的事情。我是不是误解了智能指针?
很可能,是的。在c++中,因为你必须自己处理这个问题(没有GC会帮你清理),所以你需要一种方法来跟踪每个对象的使用情况。
您可以手动将每个new
与delete
匹配,但这有时是困难的或不可能的,例如在上面的场景中。没有办法知道对象是否在其他地方被使用。
delete
。
话虽这么说,在这种特殊情况下根本没有太多理由使用指针。如果您正在使用std::string
,您可以通过值传递字符串,这将永远不会是一个问题。
你误解了智能指针很可能和你写的原因一样:
std::string* makeString()
而不是大多数c++程序员会写的:
std::string makeString()
你需要更好地理解c++中的对象生命周期,然后智能指针的概念就会容易得多。
您需要为您的对象找出所需的生命周期,然后使用类型系统来强制该生命周期。
从你的例子中,当你想要销毁对象时,它一点也不清楚。
在c++中,对象按值传递是很常见的(就像Java/c#/等中的基本类型一样),所以除非你需要在不同的代码段之间共享std::string
,否则通常的做法是按值返回字符串(将makeString
写成std::string makeString()
)。
如果你确实需要在多个地方引用同一个对象,你应该仔细考虑设计,并决定程序的哪个部分可以安全地控制对象的生命周期。在该位置按值创建对象,然后在其他位置传递指针和引用。
你可能误解了智能指针。在c++中,另一种选择是程序员需要跟踪动态分配对象的生命周期和使用情况。这会影响软件的设计,也会导致人为错误的出现。当您使用智能指针时,对象的生命周期基本上已经为您考虑好了。
我是在经典的c++风格中长大的(没有智能指针),所以如果需要的话,我可以这样编程,但如果你是从c++开始的,那么智能指针真的是必须的。
如果可以使用c++ 11使用共享指针。这些指针实现了一种机制,一旦它们中的最后一个被销毁,就删除分配的对象。如果您正在使用c++ 03,请使用boost的共享指针。如果两者都不能使用,请尝试将堆分配包装在您在堆栈上分配的类中,然后将引用传递给周围的类,并读取RAII wiki。
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 在c++中使用动态分配的问题
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 清理堆分配对象的良好实践或约定
- 将函数分配给具有相同签名但不同调用约定的 std::function 失败