eva*_*ing 6 c++ move-semantics c++11
所以我昨天在youtube上观看了c ++视频,遇到了一个关于C++ - 11 rvalue引用和移动语义的视频.我认为我从广义上理解这个概念,但是今天当我通过TA进行我的代码时,他问我为什么std::pair<HostName, IPAddress>& p在下面的代码中没有引用(如).在这种情况下,我根本没有考虑过这个问题,但当他问我记得有关"在C++ - 11中你通常应该使用传值的视频"时.
因此我的问题是:在下面的代码中,是否std::pair<HostName, IPAddress> p会更好std::pair<HostName, IPAddress>& p?是否会使用移动语义,它会有所作为吗?
IPAddress NameServer::lookup( const HostName& host ) const {
auto it = std::find_if( vec.begin(), vec.end(),
[host] ( std::pair<HostName, IPAddress> p ) {
return p.first == host;
} );
...
}
Run Code Online (Sandbox Code Playgroud)
And*_*owl 10
在这种情况下,您应该通过const引用传递.当您最终想要生成传递值的副本或移动时,按值传递是有意义的; 如果你不想复制或移动,特别是如果你只想观察,你应该通过by(const)引用.
这里,你的lambda谓词不需要生成它在输入中接收的对的任何副本:因此,没有理由按值传递(也不能通过vaue 捕获).
IPAddress NameServer::lookup( const HostName& host ) const {
auto it = std::find_if( vec.begin(), vec.end(),
[&host] ( std::pair<HostName, IPAddress> const& p ) {
// ^^^^^ ^^^^^^
return p.first == host;
} );
...
}
Run Code Online (Sandbox Code Playgroud)
相反,请考虑这种情况(典型的C++ 03代码):
struct A
{
A(string const& s) : _s(s) { }
private:
string _s;
};
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,由于你有移动语义,而不是通过s常量引用传递,你可以简单地传递值并将其移动到成员变量中:
struct A
{
A(string s) : _s(move(s)) { }
private:
string _s;
};
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我们总是最终生成传递的值的副本.
正如Benjamin Lindley在评论中正确指出的那样,如果这对你来说是可以接受的,你可以编写上述构造函数的重载,通过引用来引用它们的参数:
struct A
{
A(string const& s) : _s(s) { } // 1 copy
A(string&& s) : _s(move(s)) { } // 1 move
private:
string _s;
};
Run Code Online (Sandbox Code Playgroud)
上面的版本只允许为左值执行一个副本,为rvalues执行一个副本,而通过值传递的版本总是执行一个额外的移动.因此,如果移动对于您的参数类型来说是一个昂贵的操作(这不是这种情况string,但可能是其他类型的情况),这个解决方案可能更好.
但是,如果您的函数需要多个参数,那么这样做可能很麻烦.为了减少工作量,您可以编写一个单独的函数模板,该模板接受通用引用并完善其参数.StackOverflow上的此问答与主题相关.