如何解决std::move 对堆栈上的对象有帮助吗?
我今天刚看到一所大学在做这个优化:
即改变这个:
std::string somestring = "somestring";
std::map<std::string,int> myglobalmap;
std::string myfunction( const std::string& mystring,int myint )
{
myglobalmap.insert( std::pair<std::string,int>( mystring,myint ) );
}
myfunction(somestring,10)
致:
std::string somestring = "somestring";
std::map<std::string,int> myglobalmap;
std::string myfunction( std::string mystring,int myint )
{
myglobalmap[ std::move(mystring) ] = myint;
}
myfunction(somestring,10)
他声称通过复制传递值 mystring
而不是将其作为常量引用传递会更快,因为移动操作将仅对堆栈上的对象执行。但我不明白为什么这会有所帮助。我搜索了移动运算符,发现它没有 move anything,它只是让我的表达式返回一个引用。
那么,如果这是真的,那么通过复制传递值不会比通过引用传递并调用 std::move
慢,或者在这种情况下调用 std::move
是否有助于堆栈上的对象?如果我理解正确,std::move
应该只对堆上的对象有帮助。然后,用堆栈上的东西调用它应该没有帮助还是有帮助?
相关问题:
解决方法
我发现它没有移动任何东西,它只是让我的表达式返回一个引用。
这是正确的。至关重要的是,该函数的结果是一个 xvalue。
然后,如果这是真的,通过复制传递值不会比通过引用传递并调用 std::move 或调用 std::move 慢
在 std::string
的情况下(假设包含的字符串不是特别小),复制和移动比通过引用和移动的间接慢。
在您的第一个示例中,您通过引用间接并始终复制。
在第二个示例中,仅当函数参数是左值时才进行复制。当参数是右值时,第二个比第一个更快(只要存储的字符串足够长,差异就很重要)。
两个版本都有未定义的行为,因为函数被声明为返回非 void,但不返回值。
,首先,我想说这改变了 myfunction
的行为。如果键已存在于映射中,则第一个版本不会插入整数。第二个版本用新值替换整数。
也就是说,如果传递的字符串不在地图中,因此它会复制一份,这可能会稍微高效一些。如果 myfunction
是临时传递的,编译器可以移动构造(甚至优化移出),然后将其移动到映射中。虽然 std::move
不移动任何东西,但使用它会导致 map::operator[]
使用右值引用重载,这反过来可以调用 std::string 上的移动构造函数。
但是,在密钥已经存在的情况下,它可能会导致创建一个不需要的额外副本。
,我错过了问题中的一个重要点,在 myglobalmap.insert(
和新的 myglobalmap[
之前有一个锁。
也就是说,变化是这样的:
std::string somestring = "somestring";
std::map<std::string,int> myglobalmap;
std::mutex g_pages_mutex;
std::string myfunction( const std::string& mystring,int myint )
{
std::lock_guard<std::mutex> guard(g_pages_mutex);
myglobalmap.insert( std::pair<std::string,int>( mystring,myint ) );
return "";
}
myfunction(somestring,10)
致:
std::string somestring = "somestring";
std::map<std::string,int> myglobalmap;
std::mutex g_pages_mutex;
std::string myfunction( std::string mystring,int myint )
{
std::lock_guard<std::mutex> guard(g_pages_mutex);
myglobalmap[ std::move(mystring) ] = myint;
return "";
}
myfunction(somestring,10)
因此,作为@eerorika 提供的答案的扩展,执行的优化是在获取锁之前调用复制构造函数。这意味着第二个版本应该更快,因为在不持有锁的情况下执行复制。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。