简体   繁体   中英

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

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.

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM