让一个C++结构成员指向它内部的另一个成员合法吗



假设我有一个这样的结构。让结构的一个成员指向它内部的另一个成员合法吗?这些是如何储存的?

struct Foo {
int m1{};
int m2{};
int* pint{};
std::string str{};
const char* pstr{};
};

我先设置成员,然后再设置指针。这合法吗?

Foo a {
.m1 = 10,
.m2 = 15,
.str = "Hello, Earth!"
};
a.pint = &a.m1;
a.pstr = a.str.c_str();

我先设置指针,然后再设置成员。这合法吗?

Foo a {};
a.pint = &a.m1;
a.pstr = a.str.c_str();
a.m1 = 10,
a.m2 = 15,
a.str = "Hello, Earth!"

我在Godbolt.org上查看了一下,它似乎即使在最高优化级别也能工作,但我想确保它是合法的C++,以免UB海怪吞噬我的程序。

有没有一种方法我可以聚合初始化内联到结构成员的指针?像这样的东西?

Foo a {
.m1 = 10,
.m2 = 15,
.pint = // address to m2?
.str = "Hello, Earth!",
.pstr = // something.c_str()?
};

p.S.我该如何表达这个问题,寻找指向内部成员(和变体(的结构成员没有产生任何有用的结果。

编辑:我知道复制/移动因此而中断。对答复者的请求。如果可能的话,请给我指一下说明书,这样我就可以养成正确阅读和解释说明书的习惯。

这是合法的,但默认的复制/移动操作已中断。

要么添加

Foo(Foo const&)= delete;
Foo(Foo&&)=delete;
Foo&operator=(Foo const&)= delete;
Foo&operator=(Foo&&)=delete;

或者实施它们来做一些明智的事情。

基于注释

不,成员总是指向其他成员(如果有的话(。

我建议将成员变量pintpstr从指向对象的指针更改为指向成员变量的指针。

struct Foo {
int m1{};
int m2{};
std::string str{};
int Foo::* pint{nullptr};
std::string Foo::* pstr{nullptr};
};

然后,您可以毫无问题地使用默认的复制构造函数和复制赋值运算符。以下内容应该有效。

Foo a {10, 15, "Hello, Earth!", &Foo::m1, &Foo::str};
std::cout << a.*(a.pint) << std::endl;
std::cout << a.*(a.pstr) << std::endl;
// Default copy constructor works fine.
Foo b = a;
std::cout << b.*(b.pint) << std::endl;
std::cout << b.*(b.pstr) << std::endl;
// Default copy assignment works fine.
Foo c;
c = a;
std::cout << c.*(c.pint) << std::endl;
std::cout << c.*(c.pstr) << std::endl;

看到它在工作https://ideone.com/qE1WVn.


Re:

你能回答问题的最后一部分吗(聚合初始化指向结构成员的内联指针(?

您也可以使用

struct Foo {
int m1{};
int m2{};
std::string str{};
int Foo::* pint{&Foo::m1};
std::string Foo::* pstr{&Foo::str};
};

Foo a {
.m1 = 10,
.m2 = 15,
.str = "Hello, Earth!",
.pint = &Foo::m2,
.pstr = &Foo::str
};

最新更新