代码之家  ›  专栏  ›  技术社区  ›  Nikola Smiljanić

如何编译?(删除const对象的成员)

c++
  •  3
  • Nikola Smiljanić  · 技术社区  · 15 年前

    我希望在复制构造函数中有一个错误,但这可以用MSVC10编译。

    class Test
    {
    public:
        Test()
        {
            p = new int(0);
        }
    
        Test(const Test& t)
        {
            delete t.p; // I would expect an error here
        }
    
        ~Test()
        {
            delete p;
        }
    
    private:
        int* p;
    };
    
    4 回复  |  直到 15 年前
        1
  •  3
  •   Timo Geusch    15 年前

    你在这里遇到的问题是你没有改变 p 本身(因此) 保持不变,因为你没有改变它的价值),但是你改变了 指向并因此在另一个间接级别上工作。这是可能的,因为删除与指针关联的内存不会改变指针本身。

    从严格意义上讲,对象的常量是被保留的,即使它的逻辑常量在你从任何东西的下面拉出地毯时被违反了。 指向。

    正如john在注释中提到的,如果不能删除const对象中的指针指向的对象,那么最终将导致内存泄漏,因为在对象之后无法正确清理。

        2
  •  4
  •   David Rodríguez - dribeas    15 年前

    delete on a pointer (other than controlling access to the destructors). 你能听到的第一件事是 不修改指针,而是修改指向的对象。这可以通过打印指针轻松检查( std::cout << static_cast<void*>(p); ) before and after a delete, so even if the pointer is constant the operation is not 修改 它。

    A little less intuitive is the fact that you can 删除 指向常数元素的指针 删除 当然可以修改尖元素。But the language needed to be able to destruct constant objects when they fell out of scope (think { const mytype var(args); } )因此常量不能真正影响销毁对象的能力,如果允许自动变量这样做,那么更改动态分配对象的行为就没有多大意义。所以最后,这也是允许的。

        3
  •  2
  •   JonH    15 年前

    常量是不变的,但这不能保证它们不能被删除。如果不允许删除,您将如何删除对象。

    如果您试图修改t.p,那么会抛出一个错误,因为t是const。但是删除t是很正常的,即使它是常数。

        4
  •  0
  •   stinky472    15 年前

    有:

    int* const p;
    

    …does not disallow operator delete from being called on . 有 const int* also does not disallow operator delete from being called on it.

    典型的operator delete实现采用void*,任何指针都将隐式转换为它(实际上,这可能是采用void*的标准行为,或者是实现一个全局operator delete(可以删除任何内容)的唯一合理方法)。另外,作为一个有趣的消息,可以实现自己的重载操作符delete(全局删除或每个类删除),它采用void*,并且只需要释放new分配的内存。析构函数调用是在编译器调用operator delete之前隐式添加的;operator delete在其实现中不调用dtor。

    It is also worth noting that having const Test& 在这种情况下,基本上修改成员, int* p so that it's analogous to int* const p 不是 int const* p const int* p .

    因此:

    Test::Test(const Test& other)
    {
        *other.p = 123; // this is valid
        other.p = NULL; // this is not valid
    }
    

    换句话说,指针地址是不可变的,但指针不是。我经常在这里遇到很多关于成员函数常量和它对作为指针的数据成员的影响的混淆。了解这一点将使我们对迭代器和const_迭代器之间需要分离的原因之一有一点了解。