xml*_*lmx 32 c++ stl rvalue-reference language-lawyer pass-by-rvalue-reference
#include <set>
#include <string>
#include <cassert>
using namespace std::literals;
int main()
{
auto coll = std::set{ "hello"s };
auto s = "hello"s;
coll.insert(std::move(s));
assert("hello"s == s); // Always OK?
}
Run Code Online (Sandbox Code Playgroud)
C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?
Ser*_*eyA 26
明确明确的NO。Standard没有这种保证,这就是为什么try_emplace存在的原因。
请参阅注释:
与insert或emplace不同,如果不执行插入操作,这些函数就不会从rvalue参数移出,这使得操作值仅为移动类型的映射(例如)变得容易
std::map<std::string, std::unique_ptr<foo>>。此外,与分别try_emplace对待keyd和arguments_type的情况不同,与不同emplace,要求参数构造avalue_type(即astd::pair)
没有。
尽管@NathanOliver指出,并且仅当没有等效键时,才会插入元素,但不能保证不会修改参数。
实际上,[map.modifiers]表示以下内容
template <class P>
pair<iterator, bool> insert(P&& x);
Run Code Online (Sandbox Code Playgroud)
相当于
return emplace(std::forward<P>(x)).
在哪里emplace可以完美地提出论点以构造另一个论点P,从而x保持某种有效但不确定的状态。
这是一个示例,该示例还演示(未证明)使用std::map(关联容器)时,值会稍微移动一点:
#include <iostream>
#include <utility>
#include <string>
#include <map>
struct my_class
{
my_class() = default;
my_class(my_class&& other)
{
std::cout << "move constructing my_class\n";
val = other.val;
}
my_class(const my_class& other)
{
std::cout << "copy constructing my_class\n";
val = other.val;
}
my_class& operator=(const my_class& other)
{
std::cout << "copy assigning my_class\n";
val = other.val;
return *this;
}
my_class& operator=(my_class& other)
{
std::cout << "move assigning my_class\n";
val = other.val;
return *this;
}
bool operator<(const my_class& other) const
{
return val < other.val;
}
int val = 0;
};
int main()
{
std::map<my_class, int> my_map;
my_class a;
my_map[a] = 1;
std::pair<my_class, int> b = std::make_pair(my_class{}, 2);
my_map.insert(std::move(b)); // will print that the move ctor was called
}
Run Code Online (Sandbox Code Playgroud)