У нас будет простой класс:

class Var
{
public:
    explicit Var(const std::string& name, const double v) 
        : value(v), ref(value), _name(name) {};
    ~Var() {};

    double value{};
    double& ref;

    void print()
    {
        std::cout << _name << ":\n";
        std::cout << "\tvalue = " << value << " (" << &value << ")\n";
        std::cout << "\t  ref = " << ref << " (" << &ref << ")\n\n";
    }

private:
    std::string _name;
};

В этом случае все нормально:

Var v0("v0", 0.0);
Var v1("v1", 1.0);
Var v2("v2", 2.0);

v0.print();
v1.print();
v2.print();

Выход:

v0:
 value = 0 (000000DDE3D3F878) 
 ref = 0 (000000DDE3D3F878) 
v1:
 value = 1 (000000DDE3D3F8E8) 
 ref = 1 (000000DDE3D3F8E8) 
v2: 
 value = 2 (000000DDE3D3F958) 
 ref = 2 (000000DDE3D3F958)

Но когда объекты помещаются в вектор, переменная ref одинакова для всех объектов.

vector<Var> V{};
for (size_t i = 0; i < 3; i++)
{
    std::string name = "V[" + std::to_string(i) + "]";
    V.push_back(Var(name, i));
}

for (size_t i = 0; i < 3; i++)
    V[i].print();

Выход:

V[0]:
    value = 0 (000002B594F55C70)                                                      
      ref = 2 (000000DDE3D3FA88)
V[1]:
    value = 1 (000002B594F55CA8)                                                      
      ref = 2 (000000DDE3D3FA88)
V[2]:
    value = 2 (000002B594F55CE0)                                                      
      ref = 2 (000000DDE3D3FA88) 

Что я делаю не так?

Blockquote

3
hermann.minkowski 6 Окт 2020 в 23:53

1 ответ

Лучший ответ

std::vector требует правильно написанного оператора присваивания.

Тот, который предоставляет компилятор, бесполезен для вашего класса, поскольку ссылка не возвращается. Так что вам нужно написать это самому. И это нетривиально:

Оператор присваивания со ссылочными элементами

Однако лучше всего отбросить член ссылочного класса.

4
Bathsheba 6 Окт 2020 в 21:01