1

I want to re-define [] operator for a vector. I thought the simplest way to achieve this is to create my own class, say something like this (this is a simplified example):

class MyVec { private: std::vector<double> x; // I don't need a copy in here, it could be a reference public: MyVec(const std::vector<double>& y) { x = y; } double operator[](int i) { return x[i-1]; } }; 

Now the problem is that I basically do not need to copy data to x, I could store a reference to it, but as far as I know, I cannot use uninitialized references in class. Nonetheless, maybe there is some kind of workaround for this to work without copying the data?

16
  • what about inheritance ? Commented Feb 9, 2017 at 9:16
  • What do you mean, "class construction does not allow for this" ? Commented Feb 9, 2017 at 9:16
  • "class construction does not allow for this" is a claim of impossibility for what you want readers to implement for you. Commented Feb 9, 2017 at 9:17
  • I don't think it is a good idea to inherit a std class. Commented Feb 9, 2017 at 9:17
  • @MartinZhai: Some standard library classes, including std::stack, are expressively designed to be inherited from (std::stack has a protected data member). So clearly the ungoodness of the idea does not cover all cases. In my opinion it covers only a few special cases, that are usually not of any practical importance. Commented Feb 9, 2017 at 9:20

2 Answers 2

3

class construction does not allow for this

It does, you just need to use the member initializer list. Using it is the recommended way of initializing class members from the constructor - you should not use the constructor body for that.

class MyVec { private: const std::vector<double>& x; public: MyVec(const std::vector<double>& y) : x{y} { } double operator[](int i) { return x[i-1]; } }; 

wandbox example


Note that if you take a const& in the constructor, you need to store a const&, otherwise you lose the const-ness of passed constructor argument.

Sign up to request clarification or add additional context in comments.

3 Comments

It is a little dangerous since the outside vector may be destroyed before MyVec object. Any ideas?
@MartinZhai: not much you can do - just be careful and document the semantics of MyVec. C++ doesn't really have a way to guard the user against that situation... Rust's borrow checker is one of the selling points of the language and generates a compile-time error in case of the situation you described.
@MartinZhai: C++ does not support scope-limited ownership, but Rust does. One needs language support for that. Rust provides it.
2

For the implmentation of the constructor like MyVec(const std::vector<double>& y) { x = y; }, member x will be default constructed and then assigned by y in the constructor's body. But reference members can't be default constructed.

So if you declare the member as reference you have to initialize them by member initializer list:

For members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

e.g.

class MyVec { private: const std::vector<double>& x; // it's a reference (to const) public: MyVec(const std::vector<double>& y) : x(y) {} double operator[](int i) { return x[i-1]; } }; 

Note that for this case the member has to be declared as reference to const, because the parameter type of the constructor is reference to const.

1 Comment

Both answers are great but this one appeared few seconds earlier, so I'm accepting this one. Thank you both!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.