【问题标题】:Using copy ctor instead of move ctor when derived has destructor defined当派生定义了析构函数时,使用复制 ctor 而不是移动 ctor
【发布时间】:2013-03-09 03:24:28
【问题描述】:

当我向派生类添加析构函数时,当它尝试使用复制 ctor 而不是定义的移动 ctor 时出现编译器错误(使用 gcc 4.7):

#include <utility>
#include <iostream>

template <typename T>
struct Base 
{
  T value;

  Base(T&& value) :
    value(value)
  {
    std::cout << "base ctor" << std::endl;
  }

  Base& operator=(const Base&) = delete;
  Base(const Base&) = delete;

  Base& operator=(Base&& rhs)
  {
    value = rhs.value;
    std::cout << "move assignment" << std::endl;
  }

  Base(Base&& other) :
    value(other.value)
  {
    std::cout << "move ctor" << std::endl;
  }

  virtual ~Base()
  {
    std::cout << "base dtor" << std::endl;
  }
};

template <typename T>
struct Derived : public Base<T>
{
  Derived(T&& value) :
    Base<T>(std::forward<T>(value))
  {
    std::cout << "derived ctor" << std::endl;
  }

  ~Derived()
  {
    std::cout << "derived dtor" << std::endl;
  }
};

template <typename T>
Derived<T> MakeDerived(T&& value)
{
  return Derived<T>(std::forward<T>(value));
}

struct Dummy {};

int main()
{
  auto test = MakeDerived(Dummy());
}

这段代码在 gcc-4.5 和 gcc-4.6 上编译得很好。 gcc-4.7 的错误是:

test.cpp: In function ‘int main()’:
test.cpp:61:34: error: use of deleted function ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’
test.cpp:37:8: note: ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:37:8: error: use of deleted function ‘Base<T>::Base(const Base<T>&) [with T = Dummy; Base<T> = Base<Dummy>]’
test.cpp:16:3: error: declared here
test.cpp: In instantiation of ‘Derived<T> MakeDerived(T&&) [with T = Dummy]’:
test.cpp:61:34:   required from here
test.cpp:54:43: error: use of deleted function ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’

我在这里遗漏了什么还是应该在 gcc 4.7 上也能正常编译?当我在 Derived 类上注释掉析构函数时,一切都很好。

gcc version 4.5.3 (Ubuntu/Linaro 4.5.3-12ubuntu2) 
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 
gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2) 

【问题讨论】:

    标签: c++ gcc


    【解决方案1】:

    错误是正确的;只有当类没有用户定义的析构函数时,才会隐式生成移动构造函数。如果添加析构函数,那么您将禁止默认移动构造函数,并尝试复制构造函数。当一个类具有不可复制的基类时,默认复制构造函数的生成被抑制,就像你的那样,所以Derived 既不可复制也不可移动。

    解决方案是简单地将移动构造函数添加到Derived

    【讨论】:

    • 我不需要为没有自己成员的派生类声明移动构造函数(除了基类中的成员)。 Derived(Derived&amp;&amp; other) : Base&lt;T&gt;(other) { } 调用基类复制构造函数,所以我尝试了一个显式的 std::move 代替,它有效。对吗?
    • @Troy 是的,没错,你需要move。到目前为止,您不需要移动构造函数的原因是编译器现在才开始更严格地符合标准。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    相关资源
    最近更新 更多