在 C++ 中删除未初始化的对象 [重复]
Posted
技术标签:
【中文标题】在 C++ 中删除未初始化的对象 [重复]【英文标题】:Deleting an uninitialised object in C++ [duplicate] 【发布时间】:2011-10-09 06:08:09 【问题描述】:在我的头文件中,我声明了一个类范围内的变量:
FaultModel<double> *fm_req_set_odom_px;
...根据配置文件的值,在类构造函数中有条件地初始化:
const char *configModel = ConfigReader->ReadString("FaultModel");
if (strcmp(configModel, "cyclic") == 0)
fm_req_set_odom_px = new CyclicFaultModel<double>();
我的问题是:我是否需要用条件包装删除以检查模型是否已初始化,或者在任何一种情况下删除它是否安全?
if (fm_req_set_odom_px != NULL) // Is this necessary?
delete fm_req_set_odom_px;
【问题讨论】:
@Kerrek SB,您可以就什么是资源管理容器进行更多合作。并不是每个人都已经熟记 C++11,谷歌搜索并没有真正给出结果 @KillianDS:它们与 C++0x 无关;智能指针和容器自有标准之前就已成为 C++ 库的一部分,使用它们而不是尝试手动管理资源(这总是容易出错,并且在出现异常时通常是不可能的)的建议已经在过去的一两年里广泛流行。 啊,好吧,我完全不清楚你的意思是智能指针等;)。 我没有说“使用 C++11”,我说的是“像 2011 年那样编写 C++,而不是像 1994 年那样”。流行的资源管理容器是shared_ptr
,它在 C++0x 中可用,或者在大多数 C++98/03 编译器中作为<tr1/memory>
中的std::tr1::shared_ptr
,或者通过<boost/shared_ptr.hpp>
。在 C++98/03 中,auto_ptr
的用途有限,而在 C++0x 中,unique_ptr
是一个轻量级容器,前提是在任何给定时间只有一个负责方持有指针。
【参考方案1】:
delete NULL;
保证为空操作,因此无需手动检查。但是,未初始化的指针变量不是NULL
,因此如果条件失败,您必须将其显式设置为NULL
:
if (strcmp(configModel, "cyclic") == 0)
fm_req_set_odom_px = new CyclicFaultModel<double>();
else
fm_req_set_odom_px = NULL;
或者,您可以在 if 语句之前无条件地将指针变量设置为NULL
:
fm_req_set_odom_px = NULL;
if (strcmp(configModel, "cyclic") == 0)
fm_req_set_odom_px = new CyclicFaultModel<double>();
【讨论】:
不过,OP 从未说过她将指针初始化为 0,这是她的代码中更明显的缺陷。 恕我直言,您应该使用 C++0x nullptr,NULL 宏不再流行:) - 编辑,Kerrek 的评论是有效的,如果指针未初始化为 nullptr,则删除是不安全的它。 我可以对 Kerrek SB 所说的内容进行多次投票... 耶 - 甚至,初始化指针变量为 NULL :-)【参考方案2】:delete
检查 NULL,不需要if (myVar != NULL) delete myVar;
。另外,考虑使用std::auto_ptr
(或其他一些智能指针容器)。这可以让你摆脱很多麻烦,例如未初始化的指针。
【讨论】:
【参考方案3】:我认为首先要问的一个更基本的问题是:您是否在构造函数中初始化指向 NULL 的指针? (例如,使用初始化列表)。
如果您没有将其初始化为 NULL,那么当您尝试删除内存的随机位时,您很可能会遇到访问冲突。 如果将其初始化为 NULL,则可以跳过 if 保护语句。
【讨论】:
【参考方案4】:不需要检查。但更好的方法是使用智能指针...
【讨论】:
您认为将delete
与空指针一起使用有什么危害?因为它没有。
我不会删除我的答案,因为我明确表示使用智能指针是更好的方法,但我坚持检查......
检查没有什么害处,只是使源代码膨胀。你说的是,“你应该总是在删除之前检查”。即使检查完全没有害处,也没有好处,所以我不明白为什么每个人都应该总是这样做。
@Steve... 很好 - 这是我的习惯,不会伤害我,但如果这是一个痛苦的症结所在,我会删除第一句话...
@Nim:我删除了我的 cmets,因为你编辑了你的帖子。【参考方案5】:
除了可以适当指导您的其他答案之外,
如果您必须使用动态分配的对象,则不要使用原始指针,而是使用智能指针。
始终使用 RAII(SBRM),它让您的生活更轻松。 这样您就不必费心显式删除任何资源,资源自己会处理它
【讨论】:
【参考方案6】:delete NULL;
没有效果,所以不需要测试。
【讨论】:
但是如果指针一开始就没有初始化为 0 或 NULL 怎么办? @CJ:delete NULL;
总是无效。 NULL 始终为 NULL - 没有要初始化的指针。 delete p;
其中p
未初始化是UB。【参考方案7】:
通常,您会改用 boost::variant
之类的东西来保留可能性。在这种情况下,基于堆的动态分配是浪费的。 boost::variant
将始终为您适当地销毁其内容,您不必担心编写自己的复制构造函数/赋值运算符。
【讨论】:
升压::可选。 -- 我想不出在这种特殊情况下提供 boost::variant 但不提供 boost::optional 的充分理由以上是关于在 C++ 中删除未初始化的对象 [重复]的主要内容,如果未能解决你的问题,请参考以下文章