vkubicki
vkubicki

Reputation: 1124

References to elements in vectors during construction

In C++, I have a class MyClass, which during construction takes a reference to an int to create an internal reference to it.

I then have a class BigClass, containing both an std::vector<int> vecInt_ and an std::vector<MyClass> vecMyClass_. The constructor of BigClass takes as an argument the size of the vectors vecInt_ and vecMyClass_. In the constructor of BigClass, I would like to have each element of vecMyClass_ use in its constructor the corresponding element of vecInt_.

How could I write that ? If I could call the constructors of vecMyClass from the body of the constructor of BigClass, that would look like that :

BigClass(int nbElem) :
    vecInt_(nbElem),
    vecMyClass_(nbElem)
{
    for (int i = 0; i < nbElem; ++i)
    {
        vecMyClass_[i](vecMyInt_[i]);
    }
}

But of course the parenthesis here would mean operator(), and not the constructor. I cannot write something like:

vecMyClass_[i] = MyClass(vecMyInt_[i]);

Because MyClass contains a reference and not a pointer, and thus referenced value can not be modified.

Upvotes: 0

Views: 60

Answers (3)

opetroch
opetroch

Reputation: 4095

It doesn't sound like a very good idea. At some point adding elements to vecMyInt_ will result in expanding the vector, i.e. allocating new memory and moving the elements there, and freeing the old memory. This means that the references kept by instances of MyClass will be invalid.

Of course this won't be a problem if you reserve the capacity beforehand, and never add elements to the vector.

Upvotes: 1

pmr
pmr

Reputation: 59811

#include <vector>
#include <iostream>

struct MyClass {
  int& x;
  MyClass(int& x) : x(x) {}
};

struct BigClass {
  BigClass(std::size_t nb_elems) : ints(nb_elems) {
    my_classes.reserve(nb_elems);
    for(int& x : ints) {
      my_classes.emplace_back(x);
    }
  }

  std::vector<int> ints;
  std::vector<MyClass> my_classes;
};

int main()
{
  BigClass b{10};
  for(int& x : b.ints) {
    x = 23;
  }

  // they are all 23
  for(auto& c : b.my_classes) {
    std::cout << c.x << std::endl;
    // change them
    c.x = 24;
  }

  // they are all 24 now
  for(auto& c : b.ints) {
    std::cout << c << std::endl;
  }
  return 0;
}

Upvotes: 0

TartanLlama
TartanLlama

Reputation: 65610

You could initialize vecMyClass_ as an empty vector and emplace_back elements into it while you construct them:

BigClass(int nbElem) :
    vecInt_(nbElem),
    vecMyClass_() //empty vector
{
    vecMyClass_.reserve(nbElem); //avoid reallocations
    for (int i = 0; i < nbElem; ++i)
    {
        vecMyClass_.emplace_back(vecInt_[i]);
    }
}

Upvotes: 1

Related Questions