Why does storing references (not pointers) in containers in C++ not work?

21,158

Solution 1

Containers store objects. References are not objects.

The C++11 specification clearly states (§23.2.1[container.requirements.general]/1):

Containers are objects that store other objects.

Solution 2

Not directly relevant to the "why", but to give an answer to the implied desire to do this, I would mention that the c++11 standard library has std::reference_wrapper to enable this. It is implicitly convertible to a reference and it is storable in standard containers.

Solution 3

As Containers store objects and references are not objects. In case you are at c++ 11, you can use std::reference_wrapper to wrap things to assignable objects.

http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.

Share:
21,158
Julian Lettner
Author by

Julian Lettner

Updated on June 02, 2020

Comments

  • Julian Lettner
    Julian Lettner about 4 years

    In my program I have a STL set.

    set<string> myStrings;
    

    To improve the efficiency of my code I changed it to hold, only pointers. (I don't need actual string copies to be stored.)

    set<string*> myStrings;
    

    I have read that it is a good practice to substitute pointers with references when possible. (Of course, only if the actual functionality of a pointer is not needed.)

    set<string&> myStrings;
    

    The latter one gives me a lot of compiler errors, though. Why is it not possible to use references as container elements?

  • mojuba
    mojuba over 13 years
    That's not a good answer. Containers in C++ can contain anything, not just objects. For example you can have set<int>, set<int*> etc. A reference is a pointer on a physical level, however because the compiler needs to instantiate functions that take references to your element type, and because C++ can't handle double references, set<int&> is impossible.
  • Benjamin Lindley
    Benjamin Lindley over 13 years
    @mojuba -- In C++, when we say objects, we mean instances of any data type, including builtins.
  • James McNellis
    James McNellis over 13 years
    @mojuba: Both int and int* are objects (in C++, "an object is a region of storage." (C++03 1.8/1)). A reference is never an object. To quote the C++ standard, "Containers are objects that store other objects" (23.1/1).
  • Oliver Charlesworth
    Oliver Charlesworth over 13 years
    @mojuba: A reference is not an object as far as the language is concerned (although it's probably implemented as a pointer under the hood in certain circumstances).
  • Martin York
    Martin York over 13 years
    @mojuba: References are NOT pointers. They are aliases and as such are not objects. Everything else you mention is an object and thus is store-able in a standard container. Even thinking of references as an implementation of pointers is simplistic and often not correct (though I suppose it is an easy way to explain references to a C programmers).
  • mojuba
    mojuba over 13 years
    Ok, but the explanation as to why a ref can't be a container element is not that "it's not an object". Just look at the actual error messages given by the compiler.
  • Benjamin Lindley
    Benjamin Lindley over 13 years
    @mojuba -- read the next two sentences, they give the exact reason.
  • mojuba
    mojuba over 13 years
    @PigBen: they give a wrong reason. If you try to compile a program that defines set<string&> you will see the exact reason.
  • Benjamin Lindley
    Benjamin Lindley over 13 years
    @mojuba -- The errors you get in your compiler are dependent upon the specific implementation of the container provided by your compiler. The standard doesn't mandate any particular implementation. The standard takes a very black box approach. It says things like "The value type of a container must be both copy constructible and assignable", without worrying about how the copying and assigning is being accomplished.
  • mojuba
    mojuba over 13 years
    Of course on paper STL is a black box, but I bet all C++ compilers will fail on set<string&> for the same reason. We are trying to answer a fairly simple question here, aren't we? Further, references are perfectly constructible and assignable. The only problem with them is that construction and assignment in case of refs have different semantics and plus these operations are ambiguous in case of double refs. That's all.
  • Billy ONeal
    Billy ONeal over 13 years
    @mojuba: No, that's not true. The compile will fail the first place the particular STL implementation tried to use the assignment operation. That could be 20 function calls deep inside the template implementation code, or 2 function calls deep, and still be all well and good w.r.t. the standard. Oh, and no, references are not assignable.
  • James McNellis
    James McNellis over 13 years
    @mojuba: "We are trying to answer a fairly simple question here, aren't we?" Yes, we are, and this answer provides the answer as clearly as I think is possible: containers store objects that must be assignable and references are neither objects nor assignable. There's really nothing more to it. The "double references" issue you bring up is a red herring; C++0x allows for reference collapsing which resolves that issue but still you cannot have a container of references because references are neither objects nor assignable.
  • mojuba
    mojuba over 13 years
    @James McNellis: I now agree your answer to the original question is formally correct, but I still don't think it is the best answer that can be given to someone who (obviously) not as experienced in C++.
  • leon22
    leon22 over 9 years