C++ 何时归还T&&;来自非模板和非成员函数
请注意,之前有关于模板函数或成员函数的答案,但此问题仅涉及非模板非成员函数。例如,std::move()返回T&,但它是一个模板函数 是否有充分的理由使用T&&作为非模板和非成员函数的返回类型,其中T是任意类型 例如,您什么时候会使用以下选项C++ 何时归还T&&;来自非模板和非成员函数,c++,c++11,c++14,C++,C++11,C++14,请注意,之前有关于模板函数或成员函数的答案,但此问题仅涉及非模板非成员函数。例如,std::move()返回T&,但它是一个模板函数 是否有充分的理由使用T&&作为非模板和非成员函数的返回类型,其中T是任意类型 例如,您什么时候会使用以下选项 T&& fn() { .... return .... } 我看到过使用这种方法的示例,但在所有示例中,开发人员误解了移动语义,应该按值返回,并利用了NRVO。有时,有一个方法可以方便地返回*此作为l值引用,这样您就可以将临时值传递给接受
T&& fn()
{
....
return ....
}
我看到过使用这种方法的示例,但在所有示例中,开发人员误解了移动语义,应该按值返回,并利用了NRVO。有时,有一个方法可以方便地返回
*此
作为l值引用,这样您就可以将临时值传递给接受l值引用的函数
func(foo_t().lval_ref())代码>
那么,人们为什么要这样做呢?假设函数将l值引用作为输出变量。如果调用方实际上不需要此输出,则可以方便地传递一个临时变量,而不是定义一些虚拟变量unused
,然后static_cast(unused)
以抑制未使用变量的任何警告
类似地,您可能希望有一个方法返回*this
作为r值引用,其使用方式与std::move()
相同。这样做可以让您拥有更大的灵活性。你可以在方法实现中做任何你想做的棘手的事情:-)有时候,有一个方法返回*this
作为l值引用是很方便的,这样你就可以把一个临时值传递给一个接受l值引用的函数
func(foo_t().lval_ref())代码>
那么,人们为什么要这样做呢?假设函数将l值引用作为输出变量。如果调用方实际上不需要此输出,则可以方便地传递一个临时变量,而不是定义一些虚拟变量unused
,然后static_cast(unused)
以抑制未使用变量的任何警告
类似地,您可能希望有一个方法返回*this
作为r值引用,其使用方式与std::move()
相同。这样做可以让您拥有更大的灵活性。你可以在方法实现中做任何你想做的棘手的事情:-)假设我们有一个粒子系统。我们希望将其实现为粒子池。这意味着我们将要一次又一次地回收相同的粒子,所以为了重用资源,我们将要传递右值
现在,假设我们的粒子寿命很短,但我们希望在它们“过期”时发生一些事情(比如增加一个整数x
),但我们仍然希望回收它们。现在,假设我们希望能够指定x
。但是,现在我们该怎么办
在移动过程中,我们希望能够调用函数来增加变量,但该变量必须波动。我们不希望将其放入析构函数中,因为这将涉及在编译时派生确切函数调用的模板,或者需要一个std::function
或函数指针从粒子内部引用函数,从而浪费空间。我们想要做的是能够接受一个即将到期的值,执行一个操作,然后转发它换句话说,我们希望在从左值到右值的转换过程中有一个副作用的离职行动。
无论您在哪个操作上执行,这都很重要--在左值到右值的转换上,或者在使用操作符=
或操作符()
接收一个粒子到另一个粒子时。要么在对象接收到值时执行此操作,要么在接收右值时执行此操作。但是,假设我们想对许多不同类型的对象执行此操作——您想为5个不同的类中的每一个编写5个或更多不同的移动函数,还是应该使用外部模板函数对这些类型进行参数化
否则你会怎么做?您仍将从对象内部使用std::move()
,但我们希望将其与对象外部的函数耦合,因为这将表示移动的副作用
科里鲁:
#包括
#包括
结构粒子{
int i;
};
模板
T&move(T&obj,int(*fn)(int),int&i){
i=fn(i);
返回(标准::移动(obj));
}
int增量(int i){返回i+1;}
int main(){
//有一些我们想通过移动而不是创建新的对象池来优化的对象池。
//我们将使用右值语义,这样我们就可以“继承”生存期而不是复制。
粒子池[2000];
//填充“粒子”。
用于(自动i=0;i<2000;++i){
池[i].i=i;
}
//执行有副作用的动作。
int j=0;
用于(自动i=0;i<1999;++i){
池[i+1]=移动(池[i],&increment,j);
std::cout假设我们有一个粒子系统。我们想把它实现为一个粒子池。这意味着我们想一次又一次地回收相同的粒子,所以为了重用资源,我们想传递右值
现在,假设我们的粒子寿命很短,但我们希望在它们“过期”(比如递增整数x
)时发生一些事情,但我们仍然希望回收它们。现在,假设我们希望能够指定x
。但是,现在我们该怎么办
移动时,我们希望能够调用函数来增加变量,但变量必须波动。我们不希望将其放入析构函数中,因为这将涉及在编译时派生确切函数调用的模板,或者需要一个std::function
或函数指针从ins引用函数我们想要做的是能够接受一个即将过期的值,做一个动作,然后
#include <iostream>
#include <string>
struct Particle {
int i;
};
template <typename T>
T&& move( T& obj, int (*fn)(int) , int& i ) {
i = fn(i);
return(std::move(obj));
}
int increment(int i) { return i+1; }
int main() {
// Have some object pool we want to optimize by moving instead of creating new ones.
// We'll use rvalue semantics so we can "inherit" lifetime instead of copying.
Particle pool[2000];
// Fill up the "particles".
for (auto i = 0; i < 2000; ++i) {
pool[i].i = i;
}
// Perform the moves with side effects.
int j = 0;
for (auto i = 0; i < 1999; ++i) {
pool[i+1] = move<Particle>(pool[i], &increment, j);
std::cout << "Moves performed: " << j << '\n';
}
}