gpt4 book ai didi

c++ - 右值引用和 auto&& 局部变量

转载 作者:可可西里 更新时间:2023-11-01 18:29:12 24 4
gpt4 key购买 nike

将局部变量定义为右值引用或转发(通用)引用有什么意义?据我所知,任何有名称的变量都是左值,并且将被视为左值。

例子:

Widget&& w1 = getWidget();
auto&& w2 = getWidget();

w1 和 w2 都是左值,如果稍后将它们作为参数传递,将被视为左值。他们的 decltype 可能不是,但这有什么区别呢?为什么有人需要以这种方式定义变量?

最佳答案

如果您有一个函数返回一个无法移动的临时对象。

Foo some_function();

auto&& f = some_function();

这是合法的。 auto f = some_function(); 要么复制(这可能代价高昂),要么编译失败(如果类也无法复制)。

一般来说,auto&& 会根据其初始化的内容推断为 r 或左值引用,如果使用临时初始化会延长其生命周期,同时让您可以将其作为左值访问。

经典的用法是“just-loop”模式:

for( auto&& x : some_range )

在生成的代码中实际上有一个auto&& x = *it;

您不能将非常量左值引用绑定(bind)到临时对象,因此您的另一个选择是 Widget const&,它不允许您在临时对象的生命周期内对其进行修改。

此技术也可用于分解复杂的表达式并查看发生了什么。只要您不使用极其脆弱的表达式模板,就可以采用表达式 a+b+c*d 并将其转换为

auto&& c_times_d = d*d;
auto&& b_plus_c_times_d = b + decltype(c_times_d)c_times_d;
auto&& c_plus_b_plus_c_times_d = c + decltype(b_plus_c_times_d)b_plus_c_times_d;

现在您可以访问生命周期延长的临时对象,您可以轻松地单步执行代码,或在复杂表达式的步骤之间引入额外的步骤:这是机械地发生的。

仅当您无法绑定(bind)每个 子表达式时,才会担心脆弱的表达式模板。 (请注意,使用 -> 可以生成无数您可能不会注意到的子表达式。)

当我想说“我正在按原样存储某个函数的返回值,而不进行复制”时,我使用 auto&&,并且表达式的类型并不重要。 auto 是我想制作本地拷贝的时候。

在通用代码中,它非常有用。

Foo const& a(Foo*);
Bar a(Bar*);

template<class T>
auto do_stuff( T*ptr ) {
auto&& x = a(ptr);
}

这里如果你传递一个 Bar* 它存储临时的,但是如果你传递一个 Foo*do_stuff 它存储 const&.

它尽其所能。

这是一个返回不可移动不可复制对象的函数示例,以及 auto&& 如何让您存储它。它在其他方面毫无用处,但它显示了它是如何工作的:

struct Foo {
Foo(&&)=delete;
Foo(int x) { std::cout << "Foo " << x << " constructed\n";
};
Foo test() {
return {3};
}

int main() {
auto&& f = test();
}

关于c++ - 右值引用和 auto&& 局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36133817/

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