[英]How to initialize a const reference member to another member (std vector) in C++ initializer list
I did the following as a cheap way to allow read-only access to a member container _numbers
via numbers
:我做了以下作为允许通过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;
}
However, doing so I see that numbers
is empty, while in other cases it will contain the same elements as _numbers
.但是,这样做我看到numbers
是空的,而在其他情况下,它将包含与_numbers
相同的元素。
To be more precise, it seems to be undefined behavior.更准确地说,它似乎是未定义的行为。 In my real example (of which this a simplified version) I have multiple reference-container pairs with this scheme, where the populated data is visible in the const-reference member for some pairs, and for some it is not.在我的真实示例中(这是一个简化版本),我有多个使用此方案的引用容器对,其中填充的数据对于某些对在 const-reference 成员中可见,而对于某些对则不可见。
Any idea whats wrong with this?知道这有什么问题吗? Any help is deeply appreciated.任何帮助深表感谢。
EDIT Here is a minimal working example:编辑这是一个最小的工作示例:
#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;
}
}
which gives the following Output when initializing Foo2 f(8)
:在初始化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
ie numbers2
does not see the contents of _numbers2
while for numbers1
it seems to work.即numbers2
没有看到的内容_numbers2
而numbers1
它似乎工作。
const vector<int>& numbers1, numbers2;
— Here, only the first variable is a reference. — 这里,只有第一个变量是引用。 You need &
before the second variable to make it a reference as well.您需要&
在第二个变量之前使其成为引用。 Then the code should work.然后代码应该可以工作。
But I have to say that what you're doing is a really bad idea .但我不得不说,你所做的真是个坏主意。 You're paying for a convenient syntax with memory overhead, non-assignability, and possibly speed overhead.您正在为具有内存开销、不可分配性和可能的速度开销的便捷语法付费。
Use getters instead: const vector<int>& numbers1() const {return _numbers1;}
.改用 getter: const vector<int>& numbers1() const {return _numbers1;}
。 Yes, you will have to type the extra ()
every time.是的,您每次都必须输入额外的()
。
Hmm... The main cause of the problem was given by @HolyBlackCat: numbers2
was not a reference but an independant copy.嗯...问题的主要原因是@HolyBlackCat 给出的: numbers2
不是参考,而是一个独立的副本。
But IMHO there is a more fundamental problem.但恕我直言,还有一个更根本的问题。 With:和:
public:
const std::vector<int>& numbers;
You promise the compiler, that once initialized, the vector referenced by numbers
will no longer change .你向编译器保证,一旦初始化, numbers
引用的向量将不再改变。 Which is a lie, because the underlying vector changes...这是谎言,因为底层向量发生了变化......
Lying to the compiler is a sure path to UB: it will work sometimes, and will suddenly break because the compiler is free to change its actual code so that no changes to _member
will be reflected in members
.对编译器说谎是通往 UB 的必经之路:它有时会工作,但会突然中断,因为编译器可以自由更改其实际代码,因此对_member
更改不会反映在members
。
Possible fixes:可能的修复:
use std::vector<int>& numbers = _numbers;
使用std::vector<int>& numbers = _numbers;
(no const
). (没有const
)。 This one will be fine, but you loose the ability to present a read only reference这个没问题,但你失去了提供只读参考的能力
get a fully initialized reference when you need it through a getter (ie a method):在需要时通过 getter(即方法)获取完全初始化的引用:
const std::vector& numbers() { return _numbers; }
Again it is fine, provided _number
no longer changes after complete initialization of Foo
再次它很好,只要在Foo
完成初始化后_number
不再改变
use a dedicated object, implicitely convertible to a vector that will be fully initialized before being used:使用一个专用对象,可以隐式转换为一个在使用前完全初始化的向量:
struct Bar { std::vector<int>_numbers; Bar(bool first) : Bar(0, first) {}; Bar(int max, bool first) { cout << max << endl; int center = max / 2; if (first) { for (int i = 0; i < center; i++) { _numbers.push_back(i); cout << "A: " << i << endl; } } else { for (int i = center; i < max; i++) { _numbers.push_back(i); cout << "B: " << i << endl; } } } operator const std::vector<int>& () { return _numbers; } }; struct Foo2 { public: const int max1; const int center1; Foo2(); Foo2(const int max1_); private: Bar _numbers1, _numbers2; public: const std::vector<int>& numbers1, &numbers2; };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.