Reputation: 657
I am struggling with miniproject, where I have to do this
const Foo &f = func(arr(1.3, 2.4, 3.8, 4.3));
Foo
is non-duplicable class containing single float
value as memeber, arr
is simple function that returns std::vector
of Foo
objects initialized with values passed as parameter into arr
.
Finally func
is defined as following:
const Foo &func(const std::vector<Foo> &in)
{
return *std::max_element(in.begin(), in.end());
}
Foo
has defined operator<
function, that determines which of the two Foo
s have bigger value, thus std::max_element
works as should. Foo
has also defined Foo(Foo &&v)
that copies value.
I know that parameter of func
is created as temporary.
Application is compilable, but after debugging, the object f
contains some random value, that is not even in passed array (since the object was already destroyed?).
Is there any possible way to change func
so this will work?
Upvotes: 0
Views: 81
Reputation: 4449
Since the result of func
is a reference to an element of the vector
passed to it, then you must ensure that the vector
argument is still alive when you access the result. Passing a temporary object (arr(1.3, 2.4, 3.8, 4.3)
) means that vector will be destroyed as soon as func
is evaluated and thus the reference returned is no good. Call func
without a temporary vector parameter and you should be fine:
auto func_arg = arr(1.3, 2.4, 3.8, 4.3);
const Foo &f = func(func_arg);
There's nothing you can change within func
to make the returned reference valid. The input must be a non-temporary.
Upvotes: 2
Reputation: 16963
If func
were to return by value, it would return a temporary object whose lifetime would be extended to that of f
.
However, the object needs to be moved from the input array since it cannot be copied. This is a problem because the input parameter is a const
reference. So provide an overload that takes a movable parameter that can bind to a temporary vector. This could be either receiving by value or taking a non-const
r-value reference.
Foo func(std::vector<Foo> && in)
// ^ ^----------------^^------- non-const r-vlaue reference
// |------------------------------- return a temporary, not a reference
{
return std::move(*std::max_element(in.begin(), in.end()));
// ^^^^^^^^^--------------------- move the result
}
Upvotes: 1