3

The following code leads to this warning (vc and gcc -Wextra):

warning C4413: 'ReferencingContainer::_vector' : reference member is initialized to a temporary that doesn't persist after the constructor exits

But I don't understand why. I thought I was only passing through the reference.

#include <vector>

struct Referencing
{
    Referencing(int const &x) : _x(x) {}
    Referencing(int const &x, int dummy) : _x(x > 5 ? x : throw "error") {} // bad code, warning is ok

    int const &_x;
};

struct Container
{
    std::vector<double> _vector;
};

struct ReferencingContainer
{
    ReferencingContainer(Container const &container)
        : _container(container)
        , _vector(container._vector.size() > 0 ? container._vector : throw "error")  // <-- warning occurs here
    {}

    Container const &_container;
    std::vector<double> const &_vector;
};

int main()
{
    Referencing test1(21);
    Referencing test2(22, 0);

    Container container;
    ReferencingContainer referencingContainer(container);

    return 0;
}

Why is the compiler not happy with my code? Do I really have to worry that my object will reference a temporary?

keinkoenig
  • 193
  • 1
  • 12
  • 1
    You also get a warning with g++ if compiling with `-Wextra`: `warning: a temporary bound to 'ReferencingContainer::_vector' only persists until the constructor exits [-Wextra]` – vsoftco May 04 '15 at 17:03
  • `void main()` This is an error. If you're going to compare compilers, you need to compile the code using the compiler switches that turn on the highest level of warnings *and* with ANSI C++ compliancy turned on. There are things in g++ that are not allowed in ANSI C++ (such as Variable Length Arrays), and the only way to detect them is to compile using the appropriate switches. – PaulMcKenzie May 04 '15 at 17:04
  • further info: http://stackoverflow.com/questions/20848132/can-an-exception-be-thrown-from-the-ternary-operator – Richard Hodges May 04 '15 at 17:13

1 Answers1

3

If you add Wextra flag you will get this warning:

px.cpp:12:83: warning: a temporary bound to ‘ReferencingContainer::_vector’ only persists until the constructor exits [-Wextra]
         , _vector(container._vector.size() > 0 ? container._vector : throw "error") // <--- warning occurs here!

which is a bug of the compiler, according to this question:

Spurious warning about binding temporary to reference member in constructor

However, as vsoftco pointed out, the warning persists in version 5.1

Other relevant questions:

  1. C++ constructor: garbage while initialization of const reference
  2. Does a const reference prolong the life of a temporary?

A possible quick fix is to pass a pointer out of the ?: expression and then dereference it.

, _vector(*(container._vector.size() > 0 ? &container._vector : throw "error"))

So what's the issue here?

Compiler tells you, usually they are polite to us. By the ref of std::vector::size, we have:

size_type size() const;

which means that when you call it in the line it creates the warning, size() will return a copy of the size of _vector, which will out of scope when the constructor goes out of scope.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • it still warns you even in g++5.1 – vsoftco May 04 '15 at 17:06
  • @vsoftco that contradicts, I think, the question I linked to. Did you check it? I have 4.8.1 version. – gsamaras May 04 '15 at 17:08
  • so the code actually does the intended, but it complains about a statement in the if-clause? – keinkoenig May 04 '15 at 17:31
  • 1
    @keinkoenig in my opinion, yes! However, I could not find a trivial work around, sorry! By the way nice question, you got my +1! – gsamaras May 04 '15 at 17:32
  • i fixed the warning by using the address-of operator within the ?: and surrounding the whole expression by a dereference operator. but i think its not really obvious to a reader why i did that.. – keinkoenig May 04 '15 at 17:35
  • Argh, so I was close after all! @keinkoenig can you cp the solution here or directly edit my answer so at least it is obvious to the readers of SO? you should put a comment in your code! – gsamaras May 04 '15 at 17:37
  • @G.Samaras i'm not sure about the warning coming from the size() call. why would it disappear using my fix, when the if-clause did not change? – keinkoenig May 05 '15 at 08:01
  • @keinkoenig it surely has to do with this part too: `container._vector` – gsamaras May 05 '15 at 13:17