假设我有以下代码:
int main()
{
std::vector<std::string> strs;
std::string var("Hello World");
// Make some modifications to 'var'
strs.push_back(std::move(var));
}
Run Code Online (Sandbox Code Playgroud)
我想指出的样本部分是使用std::move().基本上我担心push_back()电话会有副本.假设我添加的字符串非常大.我还在学习C++ 11 r值引用,所以我不确定编译器如何在不使用的情况下优化副本(如果有的话)std::move().
任何人都可以解释这是否是一个过早的优化(在所有情况下强制移动,你想避免副本,一般情况下)?如果是这样,我应该期望编译器遵循哪些模式(或者最有可能遵循),这将导致优化和自动移动?
我想补充一点,我理解自动移动如何在函数返回值上发生,因为NRVO/RVO适用.我在这里给出的具体例子不适用于RVO,所以我不确定.
Jon*_*ely 28
我不确定编译器如何在不使用的情况下优化副本(如果有的话)
std::move().
只有一个非常聪明的编译器可以优化它,所以如果副本可能很昂贵(例如一个非常长的字符串),那么最好移动它.
如果没有移动,代码实际上是一系列调用:
strlen // count "Hello World"
malloc // allocate memory for string var
strcpy // copy data into var
malloc // re-allocate vector
free // deallocate old vector
malloc // allocate new string
strcpy // copy from var to new string
free // destroy var
Run Code Online (Sandbox Code Playgroud)
随着移动它变成:
strlen // count "Hello World"
malloc // allocate memory for string var
strcpy // copy data into var
malloc // re-allocate vector
free // deallocate old vector
Run Code Online (Sandbox Code Playgroud)
从理论上讲,智能编译器可以自动进行转换,但是编译器可以查看构造函数和析构vector函数引入的所有抽象层以及成员函数是非常困难的,因此证明代码可以转换为删除a malloc和freeis复杂.
Pet*_*ter 23
其他答案过于关注我的口味问题的技术方面,所以我会尝试给出更一般的答案.
简而言之:不,使用像std :: move这样的"技巧",它在问题中描述的方式并不是过早的优化.不使用std::move它的时候也可以使用,除非已经知道代码对性能至关重要.
避免过早优化的需要有时被理解为"不要优化,直到你能证明它是必要的",但我更喜欢把它读作:"不要浪费时间解决问题,除非你知道它们需要解决".
过早优化需要花费精力来优化可能不需要优化的内容,并且通常在执行此操作时将简单问题转换为复杂问题.从这个角度来看,我会将对问题本身的任何长期思考归类为过早优化.
一个相关的例子:在性能关键代码中工作的人通常会将参数作为const引用(const std::string&)传递.因为这是他们习惯做的事情,他们将在代码中使用相同的模式,这些模式不是性能关键,即使他们可以只使用pass-by-copy(const std::string,甚至std::string).这也不是一个过早的优化.
Cas*_*Cow 20
之后std::move,在这种情况下var,原始对象必须处于有效状态,但可以保留任何值,例如,它可能是空的.
如果你知道你不打算使用它var而你只是创建了它,vector那么它并不是真正的"过早"优化,而是你想要做的事情.
vector有一个新的方法emplace_back(),它是相同的,但更清晰,并使用前向参数(这里你只是做emplace_back("Hello World")你正在做的是构建它).在您的情况下,因为您"使用var进行一些修改" emplace_back不太可能不合适.
在旧版本中,C++您可以通过push_back()对空字符串进行优化来优化副本,然后交换它.
Pau*_*aul 18
我不知道为什么每个人都建议你使用emplace_back().目的emplace_back()是通过在适当的位置构建对象来避免复制/移动操作.在这种情况下,您已经构造了对象,因此至少1次复制/移动是不可避免的.在这种情况下使用emplace_back()over 没有任何好处push_back().
否则,我同意其他所有人都说这不是一个过早的优化,因为移动语义模拟了你想要做的事情,而不是制作一个对象的副本.