有没有办法在C++中循环访问对象的不同数据成员

Is there a way to loop over different data members of an object in C++

本文关键字:对象 数据成员 访问 循环 C++ 有没有      更新时间:2023-10-16

如果我有一个由 3 个双精度组成的类对象:x、y 和 z,有没有办法在函数中循环它们?

例如

for(i in (x,y,z))
do something;

我可以用显式强制转换做类似的事情,但我想知道是否有更优雅的解决方案。

class testc {
public:
double x, y, z;
testc(double x, double y, double z)
:x(x), y(y), z(z)
{}
};
int main()
{
testc omega(1, 2, 3);
cout << *(double*)&omega << " " << *((double*)&omega +1) << " " << *((double*)&omega +2);
}

(C++20( 循环访问已知数量的公共成员:基于范围的 for 循环初始化语句中的结构化绑定

从 C++20 开始,我们可以将结构化绑定与基于范围的 for 循环初始化语句相结合(后者是 C++20 功能(:

语法

对于 (初始化语句(可选( 范围声明范围表达式( ...

具体来说,在基于范围的 for 循环中使用结构化绑定作为init 语句

#include <iostream>
class Foo {
public:
double x, y, z;
Foo(double x, double y, double z) : x(x), y(y), z(z) {}
};
int main() {
const Foo foo(1., 2., 3.);
for (auto [x, y, z] = foo; auto e : {x, y, z}) {
std::cout << e << " ";
} // 1 2 3
return 0;
}

但请注意,您只能使用结构化绑定来分解类的公共成员(在您的示例中,所有成员都是公共成员(。此外,对于基于 for 循环的范围表达式中的初始值设定项列表,您可能没有冲突的类型,这意味着此方法仅限于示例的上下文:其中所有公共成员都属于同一类型。

为什么使用结构化绑定而不是直接对类成员进行列表初始化?

现在,如果类的(公共(成员及其实例都有非常简短的名称,我们可能需要考虑省略结构化绑定,而是直接列表初始化类成员:

const Foo f(1., 2., 3.);
for (auto e : {f.x, f.y, f.z}) {
std::cout << e << " ";
} // 1 2 3

然而,尽管可以说更简短,但缺点是我们不再从编译器那里得到任何帮助来发现我们是否真的完全分解了所有公共成员(不少于,不多(,当我们使用结构化绑定时存在检查:

for (auto [x, y] = foo; auto e : {x, y}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but only 2 names were provided
for (auto [x, y, z, xx] = foo; auto e : {x, y, z, xx}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but 4 names were provided
for (auto&& i : std::vector<double>{x, y, z}){
// Do something, `i` is the double.
}

是一种方式,以创建向量为代价。我不相信编译器会将其检测为成语并进行优化。

*(&x + 1)这样的代码为了尝试达到y的行为是不确定的。(指针算术仅在数组中有效。

你不能使用std::arraystd::vectorxyz吗?