I’m having a little trouble figuring out exactly how const applies in a specific case. Here’s the code I have:
struct Widget { Widget():x(0), y(0), z(0){} int x, y, z; }; struct WidgetHolder //Just a simple struct to hold four Widgets. { WidgetHolder(Widget a, Widget b, Widget c, Widget d): A(a), B(b), C(c), D(d){} Widget& A; Widget& B; Widget& C; Widget& D; }; class Test //This class uses four widgets internally, and must provide access to them externally. { public: const WidgetHolder AccessWidgets() const { //This should return our four widgets, but I don't want anyone messing with them. return WidgetHolder(A, B, C, D); } WidgetHolder AccessWidgets() { //This should return our four widgets, I don't care if they get changed. return WidgetHolder(A, B, C, D); } private: Widget A, B, C, D; }; int main() { const Test unchangeable; unchangeable.AccessWidgets().A.x = 1; //Why does this compile, shouldn't the Widget& be const? }
Basically, I have a class called test. It uses four widgets internally, and I need it to return these, but if test was declared const, I want the widgets returned const also.
Can someone explain to me why the code in main() compiles?
Thank you very much.
This compiles because although the WidgetHolder is a const object, this const-ness does not automatically apply to objects pointed to (referenced by) the WidgetHolder. Think of it at a machine level – if the WidgetHolder object itself were held in read-only memory, you could still write to things that were pointed to by the WidgetHolder.
The problem appears to lie in this line:
As Frank mentioned, your references inside the WidgetHolder class are going to hold invalid references after the constructor returns. Therefore, you should change this to:
After you do that, it won’t compile, and I leave it as an exercise for the reader to work out the rest of the solution.