使用显式定义的默认构造函数将 unique_ptr 的类内成员初始化程序设置为 nullptr 错误

Posted

技术标签:

【中文标题】使用显式定义的默认构造函数将 unique_ptr 的类内成员初始化程序设置为 nullptr 错误【英文标题】:In-class member initializer of unique_ptr to nullptr error with explicitly defined default constructor 【发布时间】:2016-06-10 05:47:09 【问题描述】:

我有一个类模板,它使用类内成员初始化程序将 unique_ptr 分配给 nullptr。如果我使用MyClass(),一切都很好。如果我使用MyClass() = default,我会得到:

conversion from 'std::nullptr_t' to non-scalar type 'std::unique_ptr<A>' requested

这是一个无法使用 g++ 4.8.4 编译的最小示例:

#include <memory>

class A;

template <typename T>
class Test

    std::unique_ptr<A> data = nullptr;
public:

    //Test()  // works fine
    Test() = default; // compiler error

;

int main()

    Test<float> test;

有什么想法吗?

【问题讨论】:

好吧,我们不会为您最小化您(对我们而言)未知的代码。 创建 SSCCE 的目的之一是,现在您在有效的和已完成的之间有了一个基线。逐渐引入更多实际代码,直到您能够重现为止。 如果我们没有不工作的代码,我们如何告诉你为什么它不工作? @DavidDoria 它仍然为我编译:coliru.stacked-crooked.com/a/0b68a4c68c6665e2 @DavidDoria 看起来您遇到了尚未添加的编译器错误/标准功能。 it compiles 4.9.2 及以上版本。 【参考方案1】:

正如 cmets 中已经指出的,这是一个编译器错误。这不是unique_ptr 的库实现中的问题,而是在没有任何标准库头文件的情况下完全可重现的语言问题,似乎只在类模板中:

struct A  A(int); ;
struct B  A a = 1; ;
B b; // ok
template <typename T> struct C  A a = 1; ;
C<void> c; // error

幸运的是,这是一个您可以解决的编译器错误。隐式转换处理不当。强制进行显式转换,甚至 GCC 4.8 也接受它。在你的情况下,这意味着:

std::unique_ptr<A> data = std::unique_ptr<A>(nullptr);

【讨论】:

unique_ptr 默认也是 nullptr,对吧?将其显式设置为 nullptr 是好是坏? @DavidDoria 是的,这是默认设置。我能想到支持和反对明确提供初始化程序的有效论据,但我不记得在最佳实践上看到过共识。 注意不要超过 600 个字符 :) ? std::unique_ptr&lt;A&gt; data; 肯定会是一个更简单的解决方法 @DavidDoria For:默认情况下某些类型未初始化。由于类型是否未初始化并不总是很明显,因此所有类成员都应显式初始化。反对:不必要的初始化器可能会导致混乱并减损更值得阅读的逻辑。

以上是关于使用显式定义的默认构造函数将 unique_ptr 的类内成员初始化程序设置为 nullptr 错误的主要内容,如果未能解决你的问题,请参考以下文章

使用枚举和模板参数正确定义显式默认构造函数

Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到“.cpp”?

C++——构造函数和析构函数

如何在构造函数中为成员 unique_ptr 赋予默认值? [复制]

显式默认构造函数

C++17 中的显式默认构造函数