在函数调用中直接创建对象
Directly creating an object in a function call
假设函数 Foo()
接受类型为 Bar
的对象。
而不是
Bar bar(parameters);
Foo(bar);
你可以Foo(Bar(parameters);
为什么在 Foo
被定义为引用时不允许第二种情况,即 returntype Foo(Bar &bar);
一个左值引用(你指的那种,写成T&
)指的是一个左值。现在,这意味着什么的确切细节在现代 C++ 中是 kind of complicated,但基本思想是左值是您可以分配给的东西。该名称最初来自左值(其中“l”是“left”的缩写)可以出现在赋值语句的 left-hand 侧这一事实。
Non-const 具有名称的变量自然可以赋值,因此它们可以作为左值引用传递。但一般来说,临时变量不是左值,因为它们不引用可以分配给的 place。
如果您的函数不打算修改参数,您可以采用 const T&
,一个常量左值引用。这在构造函数中很常见,特别是如果构造函数只是将数据复制到它自己的存储中。如果您计划修改论点,请继续阅读。
C++(C++11 之前)中的引用有点双重职责。它们的意思是“我可以分配给这个职位”,也可以是“这是我借用的 pointer-like 东西,我不会修改”。第二个含义主要由 const T&
常量左值引用捕获。但仍有一种情况我们需要更多。具体来说,如果我有一个我永远不会再次使用的值(例如,但不一定是临时值),那么我可能想通过(可变的)对函数的引用传递它,以便函数可以解构它并且可能会重复使用其中的一部分。
一个典型的例子是 array-like 容器。假设我有一个数组 class,比如说 Vector
,它由一个指向某些数据的指针和一个大小变量组成。如果我需要复制那个变量,那么原则上我需要复制整个数组。但是如果我 知道 我永远不会再使用原始向量,我可以 move 向量,直接分配指针和大小变量并避免混乱的需要O(n) 副本。但要做到这一点,我需要的正是你所描述的。我需要一个可变指针类型,它可以采用 rvalues,或者不能出现在赋值语句的 left-hand 侧的东西。
输入右值引用,写成T&&
。这些类似于左值引用,只是它们可以占用临时位置。右值引用仍然可以修改它的参数,但知道它的参数原则上不会存在太久。所以你不应该把那个东西的地址存储在 class 中,因为它不会活太久,但你仍然可以用它做一些事情,最重要的是将数据移出它。
长话短说,如果你不想修改参数,那么你应该把你的函数写成
void Foo(const Bar& arg)
如果您需要修改参数,但您完全了解内存可能不会存在太久,那么您可以使用右值引用。
void Foo(Bar&& arg)
假设函数 Foo()
接受类型为 Bar
的对象。
而不是
Bar bar(parameters);
Foo(bar);
你可以Foo(Bar(parameters);
为什么在 Foo
被定义为引用时不允许第二种情况,即 returntype Foo(Bar &bar);
一个左值引用(你指的那种,写成T&
)指的是一个左值。现在,这意味着什么的确切细节在现代 C++ 中是 kind of complicated,但基本思想是左值是您可以分配给的东西。该名称最初来自左值(其中“l”是“left”的缩写)可以出现在赋值语句的 left-hand 侧这一事实。
Non-const 具有名称的变量自然可以赋值,因此它们可以作为左值引用传递。但一般来说,临时变量不是左值,因为它们不引用可以分配给的 place。
如果您的函数不打算修改参数,您可以采用 const T&
,一个常量左值引用。这在构造函数中很常见,特别是如果构造函数只是将数据复制到它自己的存储中。如果您计划修改论点,请继续阅读。
C++(C++11 之前)中的引用有点双重职责。它们的意思是“我可以分配给这个职位”,也可以是“这是我借用的 pointer-like 东西,我不会修改”。第二个含义主要由 const T&
常量左值引用捕获。但仍有一种情况我们需要更多。具体来说,如果我有一个我永远不会再次使用的值(例如,但不一定是临时值),那么我可能想通过(可变的)对函数的引用传递它,以便函数可以解构它并且可能会重复使用其中的一部分。
一个典型的例子是 array-like 容器。假设我有一个数组 class,比如说 Vector
,它由一个指向某些数据的指针和一个大小变量组成。如果我需要复制那个变量,那么原则上我需要复制整个数组。但是如果我 知道 我永远不会再使用原始向量,我可以 move 向量,直接分配指针和大小变量并避免混乱的需要O(n) 副本。但要做到这一点,我需要的正是你所描述的。我需要一个可变指针类型,它可以采用 rvalues,或者不能出现在赋值语句的 left-hand 侧的东西。
输入右值引用,写成T&&
。这些类似于左值引用,只是它们可以占用临时位置。右值引用仍然可以修改它的参数,但知道它的参数原则上不会存在太久。所以你不应该把那个东西的地址存储在 class 中,因为它不会活太久,但你仍然可以用它做一些事情,最重要的是将数据移出它。
长话短说,如果你不想修改参数,那么你应该把你的函数写成
void Foo(const Bar& arg)
如果您需要修改参数,但您完全了解内存可能不会存在太久,那么您可以使用右值引用。
void Foo(Bar&& arg)