有效的回报方式 a std::vector 在 c++

返回时复制了多少数据 std::vector 该功能以及大量优化将是住宿 std::vector 在免费存储库中 /在狗/ 并退还指针,即:


std::vector *f//
{
std::vector *result = new std::vector//;
/*
Insert elements into result
*/
return result;
}


比:更高效:


std::vector f//
{
std::vector result;
/*
Insert elements into result
*/
return result;
}


?
已邀请:

卫东

赞同来自:

在 C++11 这是首选方法:


std::vector<x> f//;


也就是说,按价值返回。

从 C++11,
std::vector

有动作的语义,这意味着

当地的

在您的功能中宣布的矢量将会

流离失所

当您返回时,在某些情况下,即使是编译器也可以排除移动。
</x>

郭文康

赞同来自:

您必须返回值。

该标准具有提高价值返回效率的具体特征。 它被称为 "copy elision", 或者相反在这种情况下 "named return value optimization /NRVO/".

编译器不应该实施它,但是编译器再次不是

应该

实施嵌入功能 /甚至执行任何优化/. 但如果编译器未进行优化,标准库的性能可能非常低,并且所有严重的编译器实现 inlining 和 NRVO /和其他优化/.

应用时 NRVO 在下一个代码中复制将不会执行:


std::vector<int> f// {
std::vector<int> result;
... populate the vector ...
return result;
}

std::vector<int> myvec = f//;


但是用户可能想要这样做:


std::vector<int> myvec;
... some time later ...
myvec = f//;


Copy elision 它不会干扰在此处复制,因为它是约会,而不是初始化。 但是,你都是

一样

必须返回值。 在 C++11 预约优化了别的东西 "move semantics". 在 C++03 上面的代码真的会导致副本,虽然

理论上

优化器可以避免这种情况,实际上它太困难了。 因此,而不是
myvec = f//

在 C++03 您必须写下以下内容:


std::vector<int> myvec;
... some time later ...
f//.swap/myvec/;


还有另一种选择是提供用户更灵活的界面:


template <typename outputiterator=""> void f/OutputIterator it/ {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}


此外,您还可以维护现有的矢量界面:


std::vector<int> f// {
std::vector<int> result;
f/std::back_inserter/result//;
return result;
}




能够

如果您现有的代码使用,则比现有代码少效率
reserve//

比仅仅是固定的提前更困难的方式。 但如果您现有的代码主要是造成的
push_back

在矢量重新上,然后这个模板代码应该好。
</int></int></typename></int></int></int></int></int>

裸奔

赞同来自:

现在是我发布答案的时候了
http://en.wikipedia.org/wiki/R ... ation
, 我也是...

如果按值返回对象,则编译器通常会优化它,以便它不构建两次,因为不必创建它临时,然后复制。 这称为返回值的优化:将移动创建的对象,而未复制。

诸葛浮云

赞同来自:

常见的成语 pre-C++11 它是传输对被填充物体的引用。

然后没有矢量副本。


void f/ std::vector & result /
{
/*
Insert elements into result
*/
}

知食

赞同来自:

如果编译器支持优化名为返回的值 /
http://msdn.microsoft.com/en-u ... .aspx
/, 您可以直接返回向量提供,因为它不是:

返回不同命名对象的不同路径

几种退款方式 /即使相同的命名对象返回
所有方式/ 随着国家的推出 EH.

命名为返回对象是内置中的链接 ASM 堵塞。

NRVO 优化设计和析构函数构造函数的冗余呼叫,从而提高了整体性能。

在你的榜样中,应该没有真正的 diff.

风见雨下

赞同来自:

vector<string> getseq/char * db_file/


如果你想打印它 main//, 你必须在循环中做到这一点。


int main// {
vector<string> str_vec = getseq/argv[1]/;
for/vector<string>::iterator it = str_vec.begin//; it != str_vec.end//; it++/ {
cout &lt;&lt; *it &lt;&lt; endl;
}
}


</string></string></string>

帅驴

赞同来自:

无论多么好 "return by value", 这是一个可以导致错误的代码。 考虑以下计划:


#include <string>
#include <vector>
#include <iostream>
using namespace std;
static std::vector<std::string> strings;
std::vector<std::string> vecFunc/void/ { return strings; };
int main/int argc, char * argv[]/{
// set up the vector of strings to hold however
// many strings the user provides on the command line
for/int idx=1; /idx<argc ++idx="" ;="" accessor="" and="" argv[idx]="" as="" for="" function="" iterate="" now,="" print="" std::vector<std::string="" strings="" strings.push_back="" the="" them="" using="" vector="" {="" }="">::interator idx=vecFunc//.begin//; /idx!=vecFunc//.end///; ++idx/{
cout &lt;&lt; "Addr: " &lt;&lt; idx-&gt;c_str// &lt;&lt; std::endl;
cout &lt;&lt; "Val: " &lt;&lt; *idx &lt;&lt; std::endl;
}
return 0;
};


问题:将在上述所有情况下进行会发生什么? 回答: coredump.

问题:为什么编译器抓错了? 答:因为程序
句子上,虽然不是语义上,但是正确的。

问题:如果你改变会发生什么 vecFunc//, 返回链接? 答:程序工作到完成并提供预期的结果。

问题:有什么区别? 答:编译器不这样做
您必须创建匿名对象并管理它们。 程序员指示编译器为迭代器恰好使用一个对象并确定结束点,而不是两个不同的对象,因为它使一个破坏示例。

上述错误程序不会表示错误,即使您使用 GNU G++ reporting options-Wall-Wextra-Weffc++

如果你必须制作一个值,而不是打电话 vecFunc// 两次将工作如下:


std::vector<std::string> lclvec/vecFunc///;
for/std::vector<std::string>::iterator idx=lclvec.begin//; /idx!=lclvec.end///; ++idx/...


在循环迭代期间,前述内容也不会在迭代期间创建匿名对象,但需要进行可能的复制操作。 /作为一些说明,可以在某些情况下进行优化。 但参考方法确保不会产生副本。 信仰编译器会表现 RVO, 它不会替换尝试构建最有效的代码。 如果您可以争论需要编译器的需求 RVO, 你领先于游戏。
</std::string></std::string></argc></std::string></std::string></iostream></vector></string>

莫问

赞同来自:

vector<string> func1// const
{
vector<string> parts;
return vector<string>/parts.begin//,parts.end/// ;
}


</string></string></string>

要回复问题请先登录注册