通过"this"指向析构函数中其他类/函数的指针 [英] Passing the "this" pointer to other class/function in destructor

查看:75
本文介绍了通过"this"指向析构函数中其他类/函数的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在某些主对象的析构函数中的堆栈上创建一个工作对象并将主对象的 this 指针传递给帮助对象,这是合法的C ++吗?然后,辅助对象还将调用主对象的成员函数或访问成员变量.

Is it legal C++ to create a worker-object on the stack in the destructor of some master-object and pass the this pointer of the master-object to the helper-object? The helper-object would then also call member functions of the master-object or access member-variables.

换句话说,下面的合法C ++吗?

In other words, is the following legal C++?

struct MasterClass
{
  MasterClass (int data);

  ~MasterClass ();

  int data;
};

struct WorkerClass
{
  WorkerClass (MasterClass *m) : m (m) { }

  void do_some_work () { m->data = 42; }

  MasterClass *m;
};

MasterClass::MasterClass (int data)
: data (data)
{ }

MasterClass::~MasterClass ()
{
  WorkerClass w (this);

  w.do_some_work ();
}

int main ()
{
  MasterClass m (7);
}

我知道一旦析构函数开始执行,主对象的生命周期就会结束.但是我相信在任何对象的析构函数中调用非虚拟成员函数都是合法的,该函数使用隐式 this 参数/参数.

I understand that the lifetime of the master-object ends once the destructor begins to execute. But I believe it is legal to call non-virtual member functions in the destructor of any object, which make use of the implicit this argument/parameter.

推荐答案

是,不是.

是的,因为在您展示的这个非常简短的示例中它是合法的.

Yes, because its legal in this very short example you've shown.

否,因为它可能会导致UB,所以在销毁过程中围绕对象的使用存在一些警告

No, because it might result in UB, there are some caveats surrounding usage of an object during destruction

TLDR如果您没有任何继承,那总是很好.

TLDR It's always fine if you don't have any inheritance.

现在,对于在销毁期间使用对象的情况.

Now, for the cases where it is not fine to use an object during destruction.

在以下情况下,将假定已编写以下内容

The following cases will assume the following is already written

struct V;
struct A;
struct B;
struct D;

void foo(A* a = nullptr);

struct V {
    virtual void f();
    virtual void g();
};

struct A : virtual V {
    virtual void f();
};

struct B : virtual V {
    virtual void g();
    ~B() {
        foo();
    }
};

struct D : A, B {
    virtual void f();
    virtual void g();
    ~D() {
        foo(this);
    }
};

int main() {
    D d;
}

调用虚函数

在销毁 x 时(也就是它的析构函数被调用时)

Calling virtual functions

Upon the destruction of x (aka as soon as its destructor is called)

如果虚拟函数调用使用显式类成员访问,并且对象表达式引用 x 的完整对象或该对象的基类子对象之一,但不引用 x 或其基类子对象之一,其行为是不确定的.

If the virtual function call uses an explicit class member access and the object expression refers to the complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

这意味着,如果您使用显式类成员访问来使用指向整个 x 的指针来调用虚拟函数,但是某种程度上该指针不是 x的类型或它的根据,行为是不确定的.

Which means, if you use a explicit class member access to call a virtual function with a pointer pointing to the entirety of x, but somehow the pointer isn't the type of x nor its bases, the behaviour is undefined.

void foo(A* a) {
    static auto ptr = a;
    ptr->g();  // UB when called from ~B
               // ptr refers to B, but is neither B nor its base
}

使用 typeid

如果 typeid 的操作数是指正在构造或破坏的对象,并且该操作数的静态类型既不是构造函数或析构函数的类也不是其基础之一,则该行为是不确定的.

If the operand of typeid refers to the object under construction or destruction and the static type of the operand is neither the constructor or destructor's class nor one of its bases, the behavior is undefined.

同样,如果操作数引用被破坏的对象,但由于某种原因不是对象及其基础,则行为是不确定的.

Likewise, if the operand refers to the object being destructed, yet somehow isn't the object and its bases, the behaviour is undefined.

void foo(A* a) {
    static auto ptr = a;
    typeid(*ptr);  // UB when called from ~B()
                   // ptr refers to B, but is neither B nor its base
}

使用 dynamic_cast

如果 dynamic_cast 的操作数是指正在构造或破坏的对象,并且该操作数的静态类型不是指向构造函数或析构函数自己的类或其基础之一的指针或对象,则 dynamic_cast 导致未定义的行为.

If the operand of the dynamic_­cast refers to the object under construction or destruction and the static type of the operand is not a pointer to or object of the constructor or destructor's own class or one of its bases, the dynamic_­cast results in undefined behavior.

相同的交易.

void foo(A* a) {
    static auto ptr = a;
    dynamic_cast<B*>(ptr); // UB when called from ~B()
                           // ptr refers to B, but is neither B nor its base
}

结论

现在,如果您认为这是一场惨败并且不了解发生了什么,那就不要在析构函数中的任何地方传递 this .

来自 http://eel.is/c++draft/的所有引号class.cdtor

这篇关于通过"this"指向析构函数中其他类/函数的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆