0

Say we have a class like this:

class A {
public:
    A(int aa)
        : a(aa) {
    }

    const int a;
};

with a being a public property. If I don't want anyone to mess around and change it, I must make it const, fair enough.

What I don't understand why I can't manipulate such class in a container? The simplest case is replace:

std::vector<A> v;
v.push_back(A(10)); // QVector::append() fails even here
v[0] = A(20); // no-go even for plain vector

Sure I know the technical background behind this operation (basically just overwriting memory belonging to the old instance) but my question is then how I'm supposed to manipulate such container class?

Say I want to replace every second A instance with a result from some other operation. Do I have to create new container every time?

To be honest, this discovery has caught be surprise, I've always assumed that const variables are local to the given class, i.e. they have no external side effects. Copy constructor is no help here (writing to const variable) so I don't know, maybe one of the new C++11 move ones would help here somehow?

EDIT:

You're right guys, I've been fooled by programming in Java too much. However, it still feels a little bit inconsistent. So I can't overwrite the content of my container, ok. But I can delete, swap, move it without a problem?

Miro Kropacek
  • 2,742
  • 4
  • 26
  • 41
  • 1
    What do you want to happen when you use `A a1(10); A a2(20); a2 = a1;`? Do you want to change the value of `a1.a`? – R Sahu Feb 07 '17 at 04:44
  • 1
    The problem is that assignment in C++ modifies the object in place rather than acting like Java or C# where it assigns a new object to a reference. – chris Feb 07 '17 at 04:47
  • Assignment is an operation which is going to change value of `a`, which is not permitted as it's `const`. Another example: `A a1(10); const A &a2 = a1;` - if we change `a1`, `a2` is going to change as well. Basically, you cannot "fully" copy objects with const fields at all. – yeputons Feb 07 '17 at 04:48
  • @chris: Of course, if you want the reference behavior, it's straightforward to get in C++, just by using `vector>` or `vector>` instead of `vector` – Ben Voigt Feb 07 '17 at 04:50
  • About the edit: you can destroy the object (because that invalidates all links to it, and noone should ever access the object again), but you cannot "swap" objects (because that will make their `const` fields change) and you can "move" objects only partially (e.g. you can move non-const fields, but you have to copy const fields). – yeputons Feb 07 '17 at 05:01
  • @BenVoigt, Strangely enough, a C# `List` where `S` is a `struct` with a `readonly` field still works (even direct assignment). I wondered why and it appears the tradeoff made was that `readonly` isn't really enforced on structs there. That is, an assignment will modify the memory directly, despite the `readonly`. – chris Feb 07 '17 at 05:06
  • Note that it's swap of vectors, not elements. Swap of vectors is ok because we just "swap" their inner pointers which point to begins of arrays. However, I doubt you can store non-assignable items in vectors. – yeputons Feb 07 '17 at 05:08
  • @chris: It's because .NET value types don't preserve invariants, many operations treat them as a dumb block of bytes. – Ben Voigt Feb 07 '17 at 05:09

0 Answers0