c++ - 析构函数隐藏在这段代码的什么地方?

标签 c++ c++11 rvalue-reference move-semantics move-constructor

我无法理解为什么 Foo move 构造函数会在以下示例中尝试调用 ~ptr:

#include <utility>

template <typename T, typename Policy>
class ptr {
    T * m_t;
public:
    ptr() noexcept : m_t(0) {}
    explicit ptr(T *t) noexcept : m_t(t) {}
    ptr(const ptr &other) noexcept : m_t(Policy::clone(other.m_t)) {}
    ptr(ptr &&other) noexcept : m_t(other.m_t) { other.m_t = 0; }
    ~ptr() noexcept { Policy::delete_(m_t); }
    ptr &operator=(const ptr &other) noexcept
    { ptr copy(other); swap(copy); return *this; }
    ptr &operator=(ptr &&other) noexcept
    { std::swap(m_t,other.m_t); return *this; }

    void swap(ptr &other) noexcept { std::swap(m_t, other.m_t); }

    const T * get() const noexcept { return m_t; }
    T * get() noexcept { return m_t; }
};

class FooPolicy;
class FooPrivate;
class Foo {
    // some form of pImpl:
    typedef ptr<FooPrivate,FooPolicy> DataPtr;
    DataPtr d;
public:
    // copy semantics: out-of-line
    Foo();
    Foo(const Foo &other);
    Foo &operator=(const Foo &other);
    ~Foo();

    // move semantics: inlined
    Foo(Foo &&other) noexcept
      : d(std::move(other.d)) {} // l.35 ERR: using FooDeleter in ~ptr required from here
    Foo &operator=(Foo &&other) noexcept
    { d.swap(other.d); return *this; }
};

海湾合作委员会 4.7:

foo.h: In instantiation of ‘ptr<T, Policy>::~ptr() [with T = FooPrivate; Policy = FooPolicy]’:
foo.h:34:44:   required from here
foo.h:11:14: error: incomplete type ‘FooPolicy’ used in nested name specifier

Clang 3.1-pre:

foo.h:11:14: error: incomplete type 'FooPolicy' named in nested name specifier
    ~ptr() { Policy::delete_(m_t); }
             ^~~~~~~~
foo.h:34:5: note: in instantiation of member function 'ptr<FooPrivate, FooPolicy>::~ptr' requested here
    Foo(Foo &&other) : d(std::move(other.d)) {}
    ^
foo.h:23:7: note: forward declaration of 'FooPolicy'
class FooPolicy;
      ^
foo.h:11:20: error: incomplete definition of type 'FooPolicy'
    ~ptr() { Policy::delete_(m_t); }
             ~~~~~~^~
2 errors generated.

这是怎么回事?我正在编写 move 构造函数以避免运行复制 ctors 和 dtors。请注意,这是一个试图隐藏其实现(pimpl 惯用语)的头文件,因此无法将 FooDeleter 设为完整类型。

编辑:在 Bo 的回答之后,我在所有可能的地方添加了 noexcept(在上面编辑)。但错误仍然相同。

最佳答案

您创建一个新的 Foo包含 ptr<something> 的对象成员。如果Foo构造函数失败,编译器必须为部分构造的 Foo 的任何完全构造的成员调用析构函数.

但它不能实例化~ptr<incomplete_type>() ,所以失败了。

你有一个类似的情况,有一个私有(private)析构函数。这也会阻止您创建该类型的对象(除非由 friend 或成员函数完成)。

关于c++ - 析构函数隐藏在这段代码的什么地方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9417477/

相关文章:

c++ - std::result_of 在 Visual Studio 2012 中不适用于运算符 () 具有右值参数的仿函数

c++ - 如何避免 QlistView 中的数据在双击时被清空?

c++ - 未初始化成员的警告在 C++11 上消失

c++ - 为什么 GCC 会删除我在 O3 上的代码,而不是在 O0 上?

C++ 数组和 make_unique

c++ - 如何正确地将带参数的函数传递给另一个函数?

c++ - 右值引用成员变量有什么用

c++ - Boost::Serialization:如何避免指针的双重保存? (并出现 free.c 错误)

c++ - 将整数参数转发给一个构造函数,将 float 转发给另一个构造函数

c++ - C++ 中的右值绑定(bind)混淆