【问题标题】:Do I need to initialize with nullptr?我需要用 nullptr 初始化吗?
【发布时间】:2020-04-25 21:42:32
【问题描述】:

前几天我进行了一次 C++ 面试。我必须进行代码审查...

这不是面试的例子,但它是我问题的一个很好的例子

class A{
    public:
    A(int n) : m_n{n}, m_v{new char[n]}{
    //do something
    }
    ~A(){
        if(m_v != nullptr)
        {
            //here I said it should be checked and initialized with nullptr
            delete []m_v;
            m_v = nullptr;
        }
    }
    private:
    int m_n;    
    char *m_v;

};

面试官说这样做没用。如果您删除 nullptr,则不会发生任何事情。我希望它是未定义的行为。所以我的问题是这样做的好习惯吗? (或者是强制性的)

【问题讨论】:

  • 好吧,我想说这是编码风格的一个例子。
  • delete[] m_v; 正确处理 nullptr 情况。设置m_v = nullptr; 没有实际价值,因为该对象即将成为非对象......但是,我在我的开发调试代码中这样做,因为它有助于暴露悬空指针。 (并不是说我会有一个悬空指针。)
  • 你的面试官是对的。这是完全没用的。在其他情况下,这可能不是,但在这种情况下,它是 100% 没用的。在一个定义良好的 C++ 程序中,从逻辑上讲不可能得到 delete 将上面代码设置为 nullptr 值的指针的结果。因此,这在逻辑上是没有用的。同样,此声明明确且具体地适用于这个确切的用例,并且仅适用于这个确切的用例,而不适用于其他任何情况。
  • 您的 dtor 在您的示例中是私有的。所以,你不能定义A a;。您只能定义A *a;。在这种情况下,您不能在 a 上调用 delete,因为 dtor 是私有的。

标签: c++ c++11 destructor nullptr


【解决方案1】:

不需要检查nullptr 和在delete 之后分配nullptr,因此在此示例中不应存在。

来自cppreference delete(强调我的):

对于第一种(非数组)形式,表达式必须是指向对象类型的指针或可在上下文隐式转换为此类指针的类类型,其值必须为null或指向由 new 表达式创建的非数组对象,或指向由 new 表达式创建的非数组对象的基本子对象的指针。

[...]

如果表达式不是空指针并且释放函数不是破坏性删除 (C++20 起),则删除表达式为正在被破坏的对象或每个元素调用析构函数(如果有)数组被销毁(从数组的最后一个元素到第一个元素)。

在nullptr 上调用delete 没有任何作用。

在您的示例中在delete 之后分配nullptr 是没有意义的,除非析构函数中有其他代码检查m_v 是否为nullptr。析构函数运行后m_v不存在了。

PS:这真的与风格无关。不应该编写没有机会做任何有用的代码。确实没有冒犯,但是检查nullptr并将指针设置为nullptr可以认为是cargo cult programming。

【讨论】:

  • 如果m_v 变量被外部删除(例如通过A a; delete a.getM_V();)怎么办?在那种情况下它应该被检查,不是吗?
  • @Gupta 不,在这种情况下检查nullptr 不会有一点帮助。当其他人删除指针时,指针不会神奇地变为nullptr
  • @Gupta 无论如何这在示例中是不可能的。 m_v 是私有的,从外部无法访问构造函数中创建的字符数组
  • 是的,dtor 也是私有的,所以它永远不会被调用;)
  • @Gupta 实际上也阻止了在堆栈上创建对象。你只能new它并泄露它。该评论应该是针对 OP,而不是我的错字;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多