Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;标准保证插入关联容器失败不会修改右值引用参数? #包括 #包括 #包括 使用名称空间std::literals; int main() { auto coll=std::set{“hello”s}; auto s=“hello”s; coll.insert(std::move(s)); 断言(“hello”s==s);//总是正常吗? } < > > C++标准是否保证插入关联容器的失败不会修改rValor引用参数?< /强> _C++_Stl_Language Lawyer_Rvalue Reference_Pass By Rvalue Reference - Fatal编程技术网

C++;标准保证插入关联容器失败不会修改右值引用参数? #包括 #包括 #包括 使用名称空间std::literals; int main() { auto coll=std::set{“hello”s}; auto s=“hello”s; coll.insert(std::move(s)); 断言(“hello”s==s);//总是正常吗? } < > > C++标准是否保证插入关联容器的失败不会修改rValor引用参数?< /强>

C++;标准保证插入关联容器失败不会修改右值引用参数? #包括 #包括 #包括 使用名称空间std::literals; int main() { auto coll=std::set{“hello”s}; auto s=“hello”s; coll.insert(std::move(s)); 断言(“hello”s==s);//总是正常吗? } < > > C++标准是否保证插入关联容器的失败不会修改rValor引用参数?< /强> ,c++,stl,language-lawyer,rvalue-reference,pass-by-rvalue-reference,C++,Stl,Language Lawyer,Rvalue Reference,Pass By Rvalue Reference,编号< /p> 虽然指出当且仅当没有等价键时才会插入元素,但这并不保证参数不会被修改 事实上,[map.modifiers]说 #include <set> #include <string> #include <cassert> using namespace std::literals; int main() { auto coll = std::set{ "hello"s }; auto s = "hello"s; coll.

编号< /p> 虽然指出当且仅当没有等价键时才会插入元素,但这并不保证参数不会被修改

事实上,[map.modifiers]说

#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?
}
  • (2个动作)
  • (一步)

    • 明确无误。标准没有这种保证,这就是存在的原因

      见附注:

      与insert或emplace不同,这些函数不会从右值移动 如果插入未发生,则返回参数,这使得 操作值为仅移动类型的贴图,例如
      std::map
      。此外,
      try\u emplace
      分别处理映射的_类型的键和参数,与
      emplace
      ,它需要参数来构造一个
      值\u类型
      是,一个
      std::pair

      (仅适用于C++17)

      我相信正确的答案介于纳萨诺利弗(现已删除)的答案和安迪格的答案之间

      正如AndyG指出的那样,这样的保证在一般情况下是不可能存在的:有时候,库实际上必须执行移动构造,以确定插入是否可以发生。
      emplace
      功能就是这种情况,其行为由标准规定为:

      效果:插入由
      std::forward(args).
      构造的
      value\u type
      对象
      t
      ,当且仅当容器中没有与
      t
      的键等效的元素时

      我们可以将其解释为,不管发生什么情况,都要构造对象
      t
      ,如果插入无法发生,则将其丢弃,因为值
      t
      t.first
      分别已存在于集合或映射中。由于
      std::map
      模板对插入(P&&)
      方法是根据
      emplace
      指定的,正如AndyG所指出的,它具有相同的行为。正如SergeyA指出的那样,
      try\u emplace
      方法旨在避免这个问题

      但是,在OP给出的特定示例中,插入的值的类型与容器的值类型完全相同。NathanOliver之前给出的一般要求段落规定了此类插入调用的行为:

      效果:插入
      t
      当且仅当容器中没有键等于
      t
      键的元素时


      在这种情况下,在没有插入的情况下,没有为库提供修改参数的许可。我相信,除了标准明确允许的之外,调用库函数不应该有任何明显的副作用。因此,这种情况下,
      t
      不能修改。

      @user877329
      std::set
      没有
      try\u emplace
      ,因此类型转换(或缺少类型转换)的情况不适用于它。在
      无序映射
      映射
      中,
      try\u emplace
      参数由常量引用接收,因此无法从中移动。这两种情况下的
      值都是通过完美转发接收的,因此只有通过右值引用接收时才有资格从中移动,这意味着
      try\u emplace
      无法修改参数,除非您允许。
      template <class P>
      pair<iterator, bool> insert(P&& x);
      
      #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
      }