I'm getting dangling references while using a ranged-for loop. Consider the following C++14 expression (full example program below):
for(auto& wheel: Bike().wheels_reference())
wheel.inflate();
It's output is:
Wheel()
Wheel()
Bike()
~Bike() with 0 inflated wheels.
~Wheel()
~Wheel()
Wheel::inflate()
Wheel::inflate()
Obviously something is going very wrong. Wheels are accessed beyond their lifetime and the result is 0, not the expected 2.
An easy fix is to introduce a variable for Bike
in main
. However, I do not control the code in main
or Wheel
. I can only change the struct Bike
.
Is there any way to fix this example by only changing Bike
?
A successful solution solution will either fail at compile time, or count 2 inflated tires and not touch any objects beyond their lifetimes.
Appendix: compile ready source
#include <cstdlib>
#include <iostream>
#include <array>
#include <algorithm>
using std::cout;
using std::endl;
struct Wheel
{
Wheel() { cout << " Wheel()" << endl; }
~Wheel() { cout << "~Wheel()" << endl; }
void inflate() { inflated = true; cout << " Wheel::inflate()" << endl; }
bool inflated = false;
};
struct Bike
{
Bike() { cout << " Bike()" << endl; }
~Bike() {
cout << "~Bike() with " << std::count_if(wheels.begin(), wheels.end(),
[](auto& w) { return w.inflated; }) << " inflated wheels." << endl;
}
std::array<Wheel, 2>& wheels_reference() { return wheels; }
std::array<Wheel, 2> wheels{Wheel(), Wheel()};
};
int main()
{
for(auto& wheel: Bike().wheels_reference())
wheel.inflate();
return EXIT_SUCCESS;
}
Bike
, than functionreference
should return array by value, not by reference, but I think, it's not what you want. – Lyublinauto&
couldn't bind to that. – Aeonfor(auto& wheel: Bike().wheels)
and it's fine. – Evangelinclang++ -std=c++14 ./code.cpp -o ./code
. Please try again. – Klephtmain
. – KlephtBike()
a function returning a reference to a singleton then :) I think you have come across a weakness in the standard relating to lifetime extension of temporary objects. – EvangelinBike().wheels_reference()
. Stop accessing the members of a temporary. – Farsighted