初始化引用 - 警告 C4355: 'this' : used in base member initializer list

Posted

技术标签:

【中文标题】初始化引用 - 警告 C4355: \'this\' : used in base member initializer list【英文标题】:Initialize a reference - warning C4355: 'this' : used in base member initializer list初始化引用 - 警告 C4355: 'this' : used in base member initializer list 【发布时间】:2010-08-18 06:24:06 【问题描述】:
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() 

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

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

有没有更好的方法我可以使用,而不需要手动分配/释放内存(好的。我知道智能指针)?

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

【问题讨论】:

【参考方案1】:

注意这是一个警告(所以它是危险的而不是非法的)。

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

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

你想通过存储引用来实现什么?

【讨论】:

【参考方案2】:

这样做是有效的。

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

【讨论】:

【参考方案3】:

根据您正在做的事情,一种方法可能是将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;
;

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

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

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;
    
;

不过,请确保您知道自己在做什么。 (或许可以重新设计?)

【讨论】:

【参考方案4】:

好吧,避免警告的一种明显方法是让 B 存储指向 A 的指针,然后您不必在 B 的构造函数/A 的初始化器列表中对其进行初始化,并且可以等到 A 的构造函数的主体正在执行中……

【讨论】:

【参考方案5】:

认真对待这个警告。您的 this 对象尚未完全构造,并且传递是不安全的(如果您不小心调用了 this 上的函数,则调用 UB)。此外,还有其他用于内存管理的技术。尝试查找分配器的 STL 设计。

您也可以使用 RAII/智能指针来达到相同的效果。

或者,您是否正在尝试编写某种垃圾收集器/内存分析器?

【讨论】:

以上是关于初始化引用 - 警告 C4355: 'this' : used in base member initializer list的主要内容,如果未能解决你的问题,请参考以下文章

如何修复警告:初始化程序周围缺少大括号?

c++ - 如何使用构造函数中的'this'初始化其他类中的引用

this引用逃逸

This引用和对象的构造以及初始化

java的this关键字理解

对象的this引用