这段代码:
#include <vector>
std::vector<float> getstdvec() {
std::vector<float> v(4);
v[0] = 1;
v[1] = 2;
v[2] = 3;
v[3] = 4;
return v;
}
int main() {
std::vector<float> v(4);
for (int i = 0; i != 1000; ++i)
{
v = getstdvec();
}
}我在这里的错误理解是,函数getstdvec不应该实际分配它返回的向量。当我在valgrind/callgrind中运行它时,我看到有1001次对malloc的调用;1次用于main中的初始向量声明,1000次用于每次循环迭代。
怎么回事?我如何才能从这样的函数返回一个向量(或任何其他对象),而不必每次都分配它?
编辑:我知道我可以通过引用传递向量。我的印象是,可以(甚至更可取)编写这样一个函数,它返回一个对象,而不会导致不必要的分配。
发布于 2013-10-19 00:13:42
调用函数时,对于像std::vector<T>这样的返回类型,编译器会为返回的对象提供内存。被调用的函数负责构造它在这个内存插槽中返回的实例。
RVO/NRVO现在允许编译器省略创建本地临时对象,从它复制构造内存插槽中的返回值,析构临时对象,最后返回给调用者。相反,被调用的函数只是在返回槽的内存中直接构造本地对象,在函数结束时,它只是返回。
从调用者的角度来看,这是透明的:它为返回值提供内存,当调用的函数返回时,有一个有效的实例。调用者现在可以使用此对象,并负责调用析构函数并在以后释放内存。
这意味着RVO/NRVO仅在您调用函数构造新实例时有效,而不是在您分配它时有效。以下是可应用RVO/NRVO的示例:
std::vector<float> v = getstdvec();但是您的原始代码使用一个循环,并且在每次迭代中,需要构造来自getstdvec()的结果,并将此临时结果分配给v。RVO/NRVO不可能删除它。
发布于 2013-10-19 00:08:22
你可以通过reference...copy来传递,省略使得v= getstdvect()将v(在你的main中)直接分配给v(在你的getstdvec()中),并跳过通常与按值返回相关的副本,但它不会跳过你函数中的v(4)。为了做到这一点,您需要通过引用获取向量:
#include <vector>
void getstdvec(std::vector<float>& v){
v.resize(4);//will only realocate if v is wrong size
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4;
return v;
}
int main() {
std::vector<float> v(4);
for (int i=0; i!=1000;++i)
getstdvec(v);
}发布于 2013-10-19 00:09:57
你在你的循环中做拷贝赋值,而不是拷贝构造。RVO优化只适用于从返回值构造变量,而不是赋值给它们。
我不太明白你想解决的真正问题是什么。有了更多的细节,也许可以提供一个很好的答案来解决您的潜在问题。
按照目前的情况,要以这种方式从函数返回,您需要创建一个临时向量,以便在每次调用函数时返回。
https://stackoverflow.com/questions/19454068
复制相似问题