gpt4 book ai didi

C++完美转发: how to avoid dangling references

转载 作者:行者123 更新时间:2023-12-02 01:31:24 25 4
gpt4 key购买 nike

考虑以下问题:我有许多类,每个类都实现一个 get() 函数。以下 container1container2 是此类的示例:

struct expensive_type {
int v;
};

struct container1 {
expensive_type get() const {
return { 1 };
}
};

struct container2 {
expensive_type x;
expensive_type& get() {
return x;
}
};

我想创建一个以 CF 为模板的包装器,它实现与 C 相同的 get() 功能,但将函数应用于结果:

template<typename C, typename F>
struct wrapper {
F f;
C c;
decltype(auto) get() {
return f(c.get());
}
};

我现在想为一个简单的包装器创建一个函数f,它只是简单地返回其参数不变。我认为这会起作用:

auto f = [](auto&& x) -> decltype(auto) {
return forward<decltype(x)>(x);
};

wrapper<container1, decltype(f)> trivial_wrapper1 { f, {} };
wrapper<container2, decltype(f)> trivial_wrapper2 { f, {} };

,但不幸的是 trivial_wrapper1.get() 返回 expense_type{0} 而不是 expense_type{1}(至少对于 -O2 标志)。我猜这个问题与悬空引用有关,但我不知道如何解决它。

我的问题是:如何正确实现函数 f ,使其充当完美的身份,而不复制其参数?

为了澄清,以下是预期行为的示例:

cout << trivial_wrapper1.get().v << endl; // should print 1, prints 0 as of now
trivial_wrapper2.get().v = 2;
cout << trivial_wrapper2.c.x.v << endl; // should print 2, and it does as of now

最佳答案

这里的问题是没有通过函数进行临时扩展。当你这样做时

return f(c.get());

c是一个container1时,你按值返回,所以你有临时的。该临时变量仅存在于完整表达式的末尾,这意味着一旦 return 语句完成,它就会消失。这就是为什么你有一个悬空引用。

但这让你陷入了一些困境。 f 需要做的是按值返回(如果它有一个临时值),但这可能会复制,这可能会很昂贵。但如果您要通过中间函数传递返回值,确实没有办法解决这个问题。这会给你一个 f 就像

auto f = [](auto&& x) -> std::conditional_t<std::is_rvalue_reference_v<decltype(x)>,
std::remove_reference_t<decltype(x)>,
decltype(x)> {
return x;
};

它按右值的值返回,按左值的引用返回。

关于C++完美转发: how to avoid dangling references,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58768079/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com