初始化引用 - 警告C4355:'this':用于基本成员初始化列表

Che*_*eng 19 c++

class A;

class B {
public:
    B(A& a) : a(a) {}
private:
    A& a;
};

/* Method 1 */
/* warning C4355: 'this' : used in base member initializer list */
/*
class A {
public:
    A() : b(*this) {}

private:
    B b;
};
*/

/* Method 2 */
/* But I need to manually perform memory dellocation. */
class A {
public:
    A() { b = new B(*this); }
    ~A() { delete b; }

private:
    B* b;
};

int main() {
}
Run Code Online (Sandbox Code Playgroud)

目前,当我尝试初始化B中的引用时,我正在使用方法1.但是,方法1将标记我可以理解的警告.

因此,我必须使用方法2,使用动态内存分配.

有没有更好的方法可以使用,无需手动内存分配/解除分配(好的.我知道智能指针)?

我更喜欢方法1,只是因为我对警告不满意.

Mar*_*ork 14

请注意,这是一个警告(因此危险并非违法).

编译器担心的是您正在为尚未完全初始化的对象传递指针.因此,如果指针在B类构造函数中使用,则您处于未定义的行为.

因此,如果您使用此功能,您唯一能做的就是将指针指定给成员变量(引用或指针).但是请注意对变量的赋值,因为您可能会调用隐式强制转换(我不确定这是否实际上是一个问题,但RTTI在对象完全形成之前不可用).

你想通过存储参考来实现什么?


Did*_*set 11

这样做是有效的.

但是,您必须确保(我自己的意思是,编译器无法做到这一点),在this完全构造对象之前,不会使用它来调用虚函数.


GMa*_*ckG 7

根据您正在做的事情,一种方法可能是分解出需要的部分,AB不是A从部件继承.

struct bar_base; // interface foo wants

struct foo
{
    foo(bar_base& pX) :
    mX(pX)
    {}

    bar_base& mX;
};

struct bar_base
{
    /* whatever else */ 
protected:
    bar_base& get_base(void)
    {
        // getting `this` went here; safe because bar_base is initialized
        return *this; 
    }
};

struct bar : bar_base
{
    bar(void) :
    // bar_base is already initialized, so:
    mX(get_base())
    {}

    foo mX;
};
Run Code Online (Sandbox Code Playgroud)

显然,这取决于你在做什么.这可以确保您永远不会得到未定义的行为.

但实际上,这只是警告.如果你保证永远不会this在B的构造函数中使用,那么你很好,并且可以通过这种方式使警告静音:

struct bar;

struct foo
{
    foo(bar& pX) :
    mX(pX)
    {}

    bar& mX;
};

struct bar
{
    bar(void) :
    mX(self())
    {}

    foo mX;

private:
    bar& self(void)
    {
        // fools the warning
        return *this;
    }
};
Run Code Online (Sandbox Code Playgroud)

不过,请确保你知道自己在做什么.(也许它可以重新设计?)