乱序初始化成员 - 这样可以吗?

发布于 2024-12-13 08:48:02 字数 610 浏览 6 评论 0原文

来自对此答案的评论:

类成员按顺序初始化的声明。按照这个逻辑,下面的构造函数应该调用未定义的行为:

struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c) : a(b = c) { }
};

显然,我们在初始化 a 之前首先分配给 b 。分配给未初始化的对象应该是UB。代码与 Bar = int 一起“工作”并不奇怪,但如果我将 Bar 设为带有构造函数的重类,我会看到 b确实在 a 之前初始化。

(为了更加疯狂,我们甚至可以说 Foo(Bar c, Bar d) : a(b = c), b(d) { },仍然没有任何警告。)

然而 GCC 4.6.1没有对此发出警告。这是可以接受的、定义明确的行为,还是完全错误的?

From a comment on this answer:

Class members are initialized in their order of declaration. By this logic, the following constructor should invoke undefined behaviour:

struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c) : a(b = c) { }
};

Patently, we are assigning to b first before a has been initialized. Assigning to an uninitialized object should be UB. It's not surprising that the code "works" with Bar = int, but if I make Bar a heavy class with constructors, I see that b does indeed get initialized before a.

(For extra lunacy, we can even say Foo(Bar c, Bar d) : a(b = c), b(d) { }, still with no warning.)

Yet GCC 4.6.1 doesn't warn about this. Is this acceptable, well-defined behaviour, or is this strictly wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冷情妓 2024-12-20 08:48:02

给定一个 Bar ,其中非初始化状态实际上对赋值运算符很重要,我收到来自 GCC 的警告:

#include <iostream>
struct Bar {
    int n;
    Bar(int v) : n(v) {
            std::cout << "Bar " << n << " constructed\n";
    }
    Bar& operator=(const Bar& other) {
        std::cout << "Bar " << n << " assigned from " << other.n << "\n";
        n = other.n;
        return *this;
    }
};
struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c, Bar d) : a(b = c), b(d) { }
};

int main()
{
        Foo f(Bar(1), Bar(2));
}

test: https://ideone.com/VDZzG

test.cc: In function ‘int main()’:
test.cc:8:32: warning: ‘*((void*)(& f)+4).Bar::n’ is used uninitialized in this function [-Wuninitialized]
test.cc:23:13: note: ‘*((void*)(& f)+4).Bar::n’ was declared here

不过,我尝试过的其他编译器似乎并不关心......

Given a Bar where non-initialized state actually matters to the assignment operator, I get warnings from GCC:

#include <iostream>
struct Bar {
    int n;
    Bar(int v) : n(v) {
            std::cout << "Bar " << n << " constructed\n";
    }
    Bar& operator=(const Bar& other) {
        std::cout << "Bar " << n << " assigned from " << other.n << "\n";
        n = other.n;
        return *this;
    }
};
struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c, Bar d) : a(b = c), b(d) { }
};

int main()
{
        Foo f(Bar(1), Bar(2));
}

test: https://ideone.com/VDZzG

test.cc: In function ‘int main()’:
test.cc:8:32: warning: ‘*((void*)(& f)+4).Bar::n’ is used uninitialized in this function [-Wuninitialized]
test.cc:23:13: note: ‘*((void*)(& f)+4).Bar::n’ was declared here

Other compilers I've tried don't seem to care, though...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文