在 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 编译器中作为&lt;tr1/memory&gt; 中的std::tr1::shared_ptr,或者通过&lt;boost/shared_ptr.hpp&gt;。在 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++ 中删除未初始化的对象 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

没有 new 关键字并使用指针的 C++ 对象初始化 [重复]

C++智能指针简述:智能指针总结及补充

如何在 C++ 中删除 char* [重复]

c++的复制构造函数

构造函数未初始化对象成员数据

为啥我无法在 C++ 中初始化静态字段 [重复]