Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 何时归还T&&;来自非模板和非成员函数_C++_C++11_C++14 - Fatal编程技术网

C++ 何时归还T&&;来自非模板和非成员函数

C++ 何时归还T&&;来自非模板和非成员函数,c++,c++11,c++14,C++,C++11,C++14,请注意,之前有关于模板函数或成员函数的答案,但此问题仅涉及非模板非成员函数。例如,std::move()返回T&,但它是一个模板函数 是否有充分的理由使用T&&作为非模板和非成员函数的返回类型,其中T是任意类型 例如,您什么时候会使用以下选项 T&& fn() { .... return .... } 我看到过使用这种方法的示例,但在所有示例中,开发人员误解了移动语义,应该按值返回,并利用了NRVO。有时,有一个方法可以方便地返回*此作为l值引用,这样您就可以将临时值传递给接受

请注意,之前有关于模板函数或成员函数的答案,但此问题仅涉及非模板非成员函数。例如,std::move()返回T&,但它是一个模板函数

是否有充分的理由使用T&&作为非模板和非成员函数的返回类型,其中T是任意类型

例如,您什么时候会使用以下选项

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';
    }

}