0

我有以下代码:

struct Message
{
   explicit Message(const std::string& message) : selfMessage(message) {};
   ~Message() { std::cerr << "Message: " << selfMessage << std::endl; }
   const std::string selfMessage;
};

struct Foo
{
   Foo() : fooMessage("Foo") {}
   /// Destructor here is left intentionally non-virtual !!!
   ~Foo() { std::cerr << "~Foo" << std::endl; }

   Message fooMessage;
};

struct Bar : Foo
{
   Bar() : barMessage("Bar") {}
   ~Bar() { std::cerr << "~Bar" << std::endl; }
   Message barMessage;
};

int main()
{
  std::auto_ptr<Foo> foo(new Bar);
}

我期望以下输出:

Message: Bar
Message: Foo
~Foo()

但实际上(代码是用 编译的gccMessage: Bar据我所知barMessage没有被正确破坏。为什么?

AFAIK 非虚拟 d-tor 仅影响派生类的 dtor 调用 - 它永远不会被调用,但是派生类的堆栈分配成员呢?

谢谢,

PS我已经知道不推荐使用的std::auto_ptr<>()用法:)

4

3 回答 3

5

如果您delete通过指向基类对象的指针调用派生对象,那么您将获得未定义的行为 ,除非基类的析构函数被声明为虚拟的。

当基类上的std::auto_ptr模板化对象拥有派生类对象时,它会超出范围,这样会在实际对象是派生类类型时对基类指针类型调用 delete。

于 2012-03-13T11:18:56.090 回答
2

最终,auto_ptr调用delete myPtr(其中myPtr是 type 的成员T*)。在静态类型和动态类型不同的地方调用delete是未定义的行为。这不仅仅是不会调用派生类析构函数的情况;这是一个几乎任何事情都可能发生的情况。在更复杂的继承层次结构的情况下确实如此。

This is only relevant for dynamically allocated instances. Invoking delete on something which wasn't dynamically allocated is undefined behavior (and will typically cause all sorts of problems). And except for delete, the destructor is called on an object, not a pointer, so the static type and the dynamic type are identical.

于 2012-03-13T11:23:36.713 回答
1

Bar::barMessage is not destructed precisely because the destructos of the base is not virtual. The pointer is of type Foo, and on exiting of the scope, the std::auto_ptr dill call delete on the internal pointer, which is Undefined behavior, and in this case will destroy only the Foo subobject.

Note that there is no such thing as stack allocated members of Bar, there are members with automatic storage, but in this case as the whole object has been dynamically allocated, that is not in the stack but in the heap (C++ technically has no concept of stack/heap but understand that all the Bar object is dynamically allocated)

于 2012-03-13T11:25:05.707 回答