std::move 对堆栈中的对象有帮助吗?
Does std::move helps with objects on stack?
今天刚看到一个学院在做这个优化:
即,更改为:
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,它只是让我对 return 的表达成为一个参考。
那么,如果这是真的,通过复制传递值不会比通过引用传递它并调用 std::move
慢,或者在这种情况下调用 std::move
对堆栈中的对象有帮助吗?如果我理解正确,std::move
应该只对堆上的对象有帮助。然后,用堆栈上的东西调用它应该没有帮助还是有用?
相关问题:
- What is std::move(), and when should it be used?
- Is it possible to std::move local stack variables?
首先,我想说这改变了 myfunction
的行为。如果键已经存在于映射中,第一个版本不会插入整数。第二个版本用新值替换整数。
就是说,如果传递的字符串不在地图中,因此它会制作一个副本,这可能会稍微更有效率。如果 myfunction
传递了一个临时值,编译器可以移动构造(甚至优化移出),然后将其移入映射中。虽然 std::move
不移动任何东西,但使用它会导致 map::operator[]
使用右值引用重载,这又可以调用 std::string.
上的移动构造函数
但是,如果密钥已经存在,则可能会导致创建不需要的额外副本。
and I found out it does not move anything, it just makes my expression to return a reference.
这是正确的。至关重要的是,该函数的结果是一个 xvalue。
Then, if this is true, passing the value by copy would not be slower than passing it by reference and calling std::move or does calling std::move
在 std::string
的情况下(假设包含的字符串不是非常小),复制和移动比通过引用和移动的间接寻址慢。
在您的第一个示例中,您通过引用间接访问并始终制作副本。
在第二个示例中,仅当函数参数为左值时才进行复制。当参数是右值时,第二个比第一个快(只要存储的字符串足够长,差异显着)。
两个版本都有未定义的行为,因为函数被声明为 return 非空,但没有 return 值。
我错过了问题中的一个重点,在 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 提供的答案的扩展,执行的优化是在获取锁之前调用复制构造函数。这意味着第二个版本应该更快,因为复制是在不持有锁的情况下执行的。
今天刚看到一个学院在做这个优化:
即,更改为:
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,它只是让我对 return 的表达成为一个参考。
那么,如果这是真的,通过复制传递值不会比通过引用传递它并调用 std::move
慢,或者在这种情况下调用 std::move
对堆栈中的对象有帮助吗?如果我理解正确,std::move
应该只对堆上的对象有帮助。然后,用堆栈上的东西调用它应该没有帮助还是有用?
相关问题:
- What is std::move(), and when should it be used?
- Is it possible to std::move local stack variables?
首先,我想说这改变了 myfunction
的行为。如果键已经存在于映射中,第一个版本不会插入整数。第二个版本用新值替换整数。
就是说,如果传递的字符串不在地图中,因此它会制作一个副本,这可能会稍微更有效率。如果 myfunction
传递了一个临时值,编译器可以移动构造(甚至优化移出),然后将其移入映射中。虽然 std::move
不移动任何东西,但使用它会导致 map::operator[]
使用右值引用重载,这又可以调用 std::string.
但是,如果密钥已经存在,则可能会导致创建不需要的额外副本。
and I found out it does not move anything, it just makes my expression to return a reference.
这是正确的。至关重要的是,该函数的结果是一个 xvalue。
Then, if this is true, passing the value by copy would not be slower than passing it by reference and calling std::move or does calling std::move
在 std::string
的情况下(假设包含的字符串不是非常小),复制和移动比通过引用和移动的间接寻址慢。
在您的第一个示例中,您通过引用间接访问并始终制作副本。
在第二个示例中,仅当函数参数为左值时才进行复制。当参数是右值时,第二个比第一个快(只要存储的字符串足够长,差异显着)。
两个版本都有未定义的行为,因为函数被声明为 return 非空,但没有 return 值。
我错过了问题中的一个重点,在 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 提供的答案的扩展,执行的优化是在获取锁之前调用复制构造函数。这意味着第二个版本应该更快,因为复制是在不持有锁的情况下执行的。