简体   繁体   English

如何在 C++ 初始值设定项列表中将常量引用成员初始化为另一个成员(标准向量)

[英]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没有看到的内容_numbers2numbers1它似乎工作。

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.

相关问题 C ++将lambda嵌入const向量成员的初始化程序列表中 - C++ Embded lambda in initializer list for const vector member 如何使用std :: array构造函数参数C ++列表初始化const std :: array成员 - How to list-initialize a const std::array member using a std::array constructor argument C++ 如何初始化类 C++ 的成员常量向量 - How to initialize a member const vector of a class C++ 如何在C ++类的初始化列表中初始化member-struct? - How to initialize member-struct in initializer list of C++ class? 如何在构造函数初始值设定项列表中初始化std :: unique_ptr对象的类成员std :: vector? - How do I initialize a class member `std::vector` of `std::unique_ptr` object in the constructor initializer list? 如何在C ++中初始化静态const成员? - How to initialize a static const member in C++? 在C ++中使用静态const成员初始化另一个静态const - using static const member to initialize another static const in c++ C ++如何从值列表初始化矢量成员 - C++ how to initialize vector member from list of values 在类的成员初始化器列表中初始化std :: tuple - Initialize std::tuple in member initializer list of a class 初始化列表中const引用成员的初始化 - Initialization of const reference member in initializer list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM