<legend id='Laj4N'><style id='Laj4N'><dir id='Laj4N'><q id='Laj4N'></q></dir></style></legend>

    <small id='Laj4N'></small><noframes id='Laj4N'>

    1. <tfoot id='Laj4N'></tfoot>
        <bdo id='Laj4N'></bdo><ul id='Laj4N'></ul>
    2. <i id='Laj4N'><tr id='Laj4N'><dt id='Laj4N'><q id='Laj4N'><span id='Laj4N'><b id='Laj4N'><form id='Laj4N'><ins id='Laj4N'></ins><ul id='Laj4N'></ul><sub id='Laj4N'></sub></form><legend id='Laj4N'></legend><bdo id='Laj4N'><pre id='Laj4N'><center id='Laj4N'></center></pre></bdo></b><th id='Laj4N'></th></span></q></dt></tr></i><div id='Laj4N'><tfoot id='Laj4N'></tfoot><dl id='Laj4N'><fieldset id='Laj4N'></fieldset></dl></div>
      1. C++11 虚拟析构函数和移动特殊函数的自动生成

        时间:2023-08-02
      2. <small id='KPPOj'></small><noframes id='KPPOj'>

          <bdo id='KPPOj'></bdo><ul id='KPPOj'></ul>

              <tbody id='KPPOj'></tbody>
              <tfoot id='KPPOj'></tfoot>

              <i id='KPPOj'><tr id='KPPOj'><dt id='KPPOj'><q id='KPPOj'><span id='KPPOj'><b id='KPPOj'><form id='KPPOj'><ins id='KPPOj'></ins><ul id='KPPOj'></ul><sub id='KPPOj'></sub></form><legend id='KPPOj'></legend><bdo id='KPPOj'><pre id='KPPOj'><center id='KPPOj'></center></pre></bdo></b><th id='KPPOj'></th></span></q></dt></tr></i><div id='KPPOj'><tfoot id='KPPOj'></tfoot><dl id='KPPOj'><fieldset id='KPPOj'></fieldset></dl></div>
                <legend id='KPPOj'><style id='KPPOj'><dir id='KPPOj'><q id='KPPOj'></q></dir></style></legend>
                • 本文介绍了C++11 虚拟析构函数和移动特殊函数的自动生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  C++11 中自动生成特殊移动函数(构造函数和赋值运算符)的规则规定不能声明析构函数.逻辑大概是,如果你需要在破坏中做一些特殊的事情,那一步可能不安全.

                  The rules for auto generating special move functions (constructor and assignment operator) in C++11 specify that no destructor can be declared. The logic is presumably that, if you need to do something special in destruction, that a move may not be safe.

                  然而,为了在多态中正确调用析构函数,有必要将基类的析构函数声明为虚拟的(否则通过其基类的指针删除子类的实例将无法正确链接析构函数).

                  However, for proper destructor calls in polymorphism, it is necessary to declare a base classes' destructor as virtual (otherwise deleting an instance of a sub class through a pointer of its base class will not properly chain the destructor).

                  我假设,即使是空的析构函数也会阻止编译器自动生成特殊的移动函数.如:

                  I'm assuming, then, that even an empty destructor would prevent the compiler from automatically generating a special move functions. As in:

                  class Base {
                      virtual ~Base() { }
                  };
                  

                  但是,您可以默认析构函数,如下所示:

                  You can, however, default the destructor, as in:

                  class Base {
                      virtual ~Base() = default;
                  }
                  

                  那么问题 1:这会允许编译器自动生成特殊移动函数吗?

                  So question 1: Will this allow the compiler to auto generate special move functions?

                  然而,显式默认析构函数存在问题.至少在 GCC 4.8.2 的情况下,签名被隐式更改为 noexcept.如:

                  There is a problem with the explicit default destructor, however. In at least the case of GCC 4.8.2, the signature is implicitly changed to noexcept. As in:

                  class Base {
                      virtual ~Base() = default; // compiler changes to:
                      // virtual ~Base() noexcept;
                  }
                  

                  虽然我在析构函数中使用 noexcept 没有问题,但这会破坏以下客户端"代码:

                  While I have no problem with noexcept in a destructor, this would break the following "client" code:

                  class Sub : public Base {
                      virtual ~Sub(); // this declaration is now "looser" because of no noexcept
                  }
                  

                  所以问题 2 更重要:有没有办法允许在 C++11 中自动生成特殊的移动函数并允许适当的析构函数链接到子类(如上所述),所有这些都不会破坏子类(客户端") 代码?

                  So question 2 is more to the point: is there a way to allow auto generation of special move functions in C++11 and allow proper destructor chaining to sub classes (as described above), all without breaking subclass ("client") code?

                  推荐答案

                  1. 不,默认的析构函数仍被视为用户定义的,因此它将阻止移动操作的生​​成.还要声明移动操作 default-ed 以使编译器生成它们.

                  1. No, a defaulted destructor is still considered user defined, so it will prevent the generation of move operations. Also declare the move operations default-ed to make the compiler generate them.

                  您只需在基类中将移动操作声明为 default-ed.在派生类中,析构函数不再是用户定义的(除非您明确说明),因此不会删除移动操作.

                  You need to only declare the move operations as default-ed in the base class. In the derived class, the destructor won't be user defined anymore (unless you explicitly say so), so the move operations won't be deleted.

                  所以我要做的是:

                  class Base
                  {
                      virtual ~Base() = default;
                      Base(Base&&) = default;
                      Base& operator=(Base&&) = default;
                      // probably need to think about copy operations also, as the move disables them
                      Base(const Base&) = default;
                      Base& operator=(const Base&) = default;
                  };
                  

                  我强烈推荐可能对移动语义贡献最大的人的这个演讲:http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014

                  I highly recommend this talk by the person who contributed probably the most to the move semantics: http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014

                  或者,如果您能亲自动手,您应该阅读 Scott Meyers 的优秀著作Effective Modern 中的条款 17:了解特殊成员函数生成C++.这个问题得到了很好的解释.

                  Or, if you can get your hands on, you should read the Item 17: Understand special member function generation from Scott Meyers' excellent book Effective Modern C++. This issue is excellently explained.

                  PS:我认为您应该多考虑一下您的基类.大多数情况下,您应该使用抽象类,因此无需复制/移动它们的实例.

                  PS: I think you should think a bit more about your base classes. Most of the time, you should use abstract classes, so there will be no need to copy/move instances of them.

                  PSS:我认为默认情况下,析构函数在 C++11/14 中被标记为 noexcept,所以不明确指定它不会导致任何问题:

                  PSS: I think by default destructors are marked noexcept in C++11/14, so not explicitly specifying it shouldn't cause any problems:

                  继承构造函数和隐式声明的默认值构造函数、复制构造函数、移动构造函数、析构函数、复制赋值运算符,移动赋值运算符都是noexcept(true) 默认情况下,除非他们需要调用一个函数即 noexcept(false),在这种情况下,这些函数是noexcept(false).

                  Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false), in which case these functions are noexcept(false).

                  这篇关于C++11 虚拟析构函数和移动特殊函数的自动生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:不能因为类不是多态而沮丧吗? 下一篇:为什么我不能从派生类的实例访问受保护的成员

                  相关文章

                  最新文章

                  <tfoot id='Se6GK'></tfoot>

                • <small id='Se6GK'></small><noframes id='Se6GK'>

                • <legend id='Se6GK'><style id='Se6GK'><dir id='Se6GK'><q id='Se6GK'></q></dir></style></legend>

                    <i id='Se6GK'><tr id='Se6GK'><dt id='Se6GK'><q id='Se6GK'><span id='Se6GK'><b id='Se6GK'><form id='Se6GK'><ins id='Se6GK'></ins><ul id='Se6GK'></ul><sub id='Se6GK'></sub></form><legend id='Se6GK'></legend><bdo id='Se6GK'><pre id='Se6GK'><center id='Se6GK'></center></pre></bdo></b><th id='Se6GK'></th></span></q></dt></tr></i><div id='Se6GK'><tfoot id='Se6GK'></tfoot><dl id='Se6GK'><fieldset id='Se6GK'></fieldset></dl></div>
                      • <bdo id='Se6GK'></bdo><ul id='Se6GK'></ul>