Brykyz
Brykyz

Reputation: 657

C++ Return const reference from function with temporary parameter of custom non-duplicable object

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 Foos 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

Answers (2)

Woodford
Woodford

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

JaMiT
JaMiT

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

Related Questions