如何解决如何在 C++ 初始值设定项列表
为了允许通过 _numbers
对成员容器 numbers
进行只读访问,我做了以下操作:
class Foo {
Foo() : _numbers({}),numbers(_numbers) {
// some code that populates `numbers` via `numbers.push_back(...)`
}
private:
std::vector<int> _numbers;
public:
const std::vector<int>& numbers;
}
但是,这样做我看到 numbers
是空的,而在其他情况下,它将包含与 _numbers
相同的元素。
更准确地说,它似乎是未定义的行为。 在我的真实示例中(这是一个简化版本),我有多个使用此方案的引用容器对,其中填充的数据在 some 对的 const-reference 成员中可见,而对于某些它不是。
知道这有什么问题吗?任何帮助深表感谢。
编辑这是一个最小的工作示例:
#include <vector>
struct Foo2 {
public:
const int max1;
const int center1;
Foo2(const int max1_);
private:
std::vector<int> _numbers1,_numbers2;
public:
const std::vector<int>& numbers1,numbers2;
};
Foo2::Foo2(const int max1_)
: max1(max1_),center1(max1_/2),_numbers1({}),_numbers2({}),numbers1(_numbers1),numbers2(_numbers2)
{
cout << max1 << endl;
for (int i=0; i<center1; i++) {
_numbers1.push_back(i);
cout << "A: " << i << endl;
}
for (int i=center1; i<max1; i++) {
_numbers2.push_back(i);
cout << "B: " << i << endl;
}
for (int i: numbers1) {
cout << "A: " << i << endl;
}
for (int i: numbers2) {
cout << "B: " << i << endl;
}
}
在初始化 Foo2 f(8)
时给出以下输出:
8
A: 0
A: 1
A: 2
A: 3
B: 4
B: 5
B: 6
B: 7
A: 0
A: 1
A: 2
A: 3
即numbers2
看不到 _numbers2
的内容,而 numbers1
似乎可以工作。
解决方法
const vector<int>& numbers1,numbers2;
— 在这里,只有第一个变量是引用。您需要在第二个变量之前使用 &
才能使其成为引用。然后代码应该可以工作了。
但我不得不说你所做的真是个坏主意。您正在为具有内存开销、不可分配性和可能的速度开销的便捷语法付出代价。
改用 getter:const vector<int>& numbers1() const {return _numbers1;}
。是的,您每次都必须输入额外的 ()
。
嗯...问题的主要原因是@HolyBlackCat 给出的:numbers2
不是引用而是一个独立的副本。
但是恕我直言,还有一个更根本的问题。与:
public:
const std::vector<int>& numbers;
您承诺编译器,一旦初始化,numbers
引用的向量将不再改变。这是谎言,因为底层向量发生了变化......
向编译器说谎是通往 UB 的必经之路:它有时会工作,但会突然中断,因为编译器可以自由更改其实际代码,因此 _member
的任何更改都不会反映在 {{1 }}。
可能的修复:
-
使用
members
(没有std::vector<int>& numbers = _numbers;
)。这个没问题,但你失去了提供只读参考的能力 -
在需要时通过 getter(即方法)获取完全初始化的引用:
const
同样没问题,只要在
const std::vector& numbers() { return _numbers; }
完成初始化后_number
不再变化 -
使用专用对象,隐式转换为向量,在使用前将完全初始化:
Foo
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。