c++ - 为什么 struct 属性声明和初始化顺序会这样?
问题描述
我最近遇到了这个:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm> //sort function
#include <functional> //functions utilities
#include <random> //random numbers generation
using namespace std;
default_random_engine generator;
uniform_int_distribution<int> distribution(0,9999);
auto randomer = bind(distribution, generator);
struct Test_struct {
string ord_as_string;
int ord;
Test_struct() :
ord(randomer()),
ord_as_string(to_string(ord))
{}
};
int main() {
vector<Test_struct> my_vector;
for(int i = 0; i < 100; ++i) my_vector.push_back(Test_struct());
for(auto& e: my_vector)
cout << e.ord_as_string << " -> " << e.ord << endl;
}
Wich 打印以下序列:
142 -> 0
0 -> 1315
1315 -> 7556
7556 -> 4586
4586 -> 5327
5327 -> 2189
2189 -> 470
470 -> 6788
6788 -> 6792
...
这是没有意义的,因为结构int
和string
属性应该引用相同的逻辑数字。所以我只是将声明更改为:
struct Test_struct {
int ord;
string ord_as_string;
Test_struct() :
ord(randomer()),
ord_as_string(to_string(ord))
{}
};
我认为它可以处理结构属性的声明顺序并且它起作用了:
0 -> 0
1315 -> 1315
7556 -> 7556
4586 -> 4586
5327 -> 5327
2189 -> 2189
470 -> 470
6788 -> 6788
...
那么,有人可以向我解释为什么ord
在其他属性之后声明但之前初始化时,引用保留在以下结构初始化中?
编辑:好的,成员按照评论中的声明顺序进行初始化,那么,为什么要这样设计呢?这对我来说毫无意义。
解决方案
您遇到了未定义的行为。成员的初始化顺序必须与声明的顺序一致。
因为它没有,所以您观察到的行为源于ord
成员未初始化并且巧合地在循环的每次迭代中重用内存中的相同位置。这个位置恰好保存了您之前在迭代中分配的值。
你可以在这里阅读初始化的顺序是什么,以及为什么会这样。总结一下链接和注释:析构函数必须以初始化的相反顺序销毁对象,并且由于可以有多个构造函数,因此必须有一个单一的事实来源,即类中的声明顺序。
推荐阅读
- ionic-framework - 在 ionic v4 中添加自定义加载微调器
- java - 从 selenium 服务器获取所有会话
- android - 如何通过意图共享任何类型的文件(.pdf、.xls、.docs)?
- angular - 如何更改 Angular Material 步进器中的状态图标?
- mysql - 如何从另一个服务器存储过程调用存储过程?
- docker - 使用 Docker 运行时如何备份和恢复 Alfresco Community
- amazon-ec2 - 与 EC2 上托管的 websocket 服务器的 ws 连接上的 Lambda 超时错误
- selenium - 当服务器使用 w3c 时,在 Edge 中获取错误消息“不允许使用 JSON 有线协议命令端点”
- kendo-grid - 导出到 Excel 按钮在 Edge 浏览器中不起作用
- azure - Azure 数据工厂:从 postgresql 数据库复制数据(或数据流)