在初始值设定项列表中使用此指针

using this pointer in initializer list

本文关键字:指针 列表      更新时间:2023-10-16
struct T
{
    int a;
};
struct C
{
    T& r;
    C(T& v) : r(v) {}
};
struct E : T
{
    T& r;
    E(T const& v) : r(*this), T(v) {}   // ok
};
struct F : C, T // base order doesn't matter here
{
    //F(T const& v) : C(*this), T(v) {}   // error : C::r is not initialized properly
    F(T const& v) : C(*static_cast<T*>(this)), T(v) {}   // ok
    //F(T const& v) : C(static_cast<T&>(*this)), T(v) {}   // ok
};
int main()
{
    T v;
    F f(v);
    f.r.a = 1;
}

尽管在初始值设定项列表中使用此指针可能会有问题,但我从未预料到这种情况发生在 POD 上,并且可能只是通过显式强制转换来修复;这是一些编译器错误或与 std 相关的问题吗?

代码不明确。

为了构造 FC基,上下文是直接初始化的,因此 13.3.1.3 适用:

C++11

13.3.1.3 通过构造函数初始化 [over.match.ctor]

对于直接初始化,候选 函数是正在初始化的对象类的所有构造函数。

包含隐式声明的复制构造函数,按 12.8:8。

C 构造函数的候选项是 C(T &) 和(默认复制构造函数) C(const C &) , 按参数列表 (F) 。 在这两种情况下,我们都有一个引用绑定(13.3.3.1.4),然后是派生到基础的转换(13.3.3.1),在后一种情况下,还有一个额外的cv资格调整,在这两种情况下给出转换的总体排名。

由于CT都是F的基类,但是是不同的类型,并且都不是另一个的基类,因此13.3.3.2:3和13.3.3.2:4中的子句都不适用,转换序列是不可区分的。

事实上,gcc-4.5.1

拒绝代码:
prog.cpp: In constructor 'F::F(const T&)':
prog.cpp:20:34: error: call of overloaded 'C(F&)' is ambiguous
prog.cpp:9:5: note: candidates are: C::C(T&)
prog.cpp:7:1: note:                 C::C(const C&)

当你尝试用*this初始化F的基本C时,编译器为C生成的复制构造函数和你定义的构造函数都T&是匹配的,因为*this的类型(F)直接派生自CT。你的演员表解决了这种歧义。

我很惊讶复制构造函数比采用T&的那个更匹配,因为我本以为它们都是同样受欢迎的。如果选择了复制构造函数,则基将从自身初始化,这会导致未定义的行为,因为引用成员将从未初始化的引用(本身)初始化。

1)永远不要在初始化列表中使用它http://msdn.microsoft.com/en-us/library/3c594ae3(v=vs.80).aspxthis 指针仅在非静态成员函数中有效。它不能在基类的初始值设定项列表中使用。

基类构造

函数和类成员构造函数在此构造函数之前调用。实际上,您已将指向未构造对象的指针传递给另一个构造函数。如果这些其他构造函数访问任何成员或在此上调用成员函数,则结果将是未定义的。在所有构造完成之前,不应使用 this 指针。

很快:C.r 由坏 poiter 初始化

结构体 C{    T&r;    C(T& v) : r(v) {}};结构 E : T{    T&r;    E(T const& v) : r(*this), T(v) {}//ok};

您需要在声明时初始化任何引用,但在这里您刚刚声明了它。这在C++是不允许的。