如何在C++中实现const-object-specific构造函数?

5vf7fwbs  于 2023-10-21  发布在  其他
关注(0)|答案(2)|浏览(137)

作为练习,我实现了一个名为Array的类来模拟std::array类的大部分功能。我努力实现的一件事是以下几点。假设我们有以下声明:

std::array<int,5> a1;
std::array<int,5> a1{};
const std::array<int,5> a1;
const std::array<int,5> a1{};

第三次初始化显示错误:
Default initialization of an object of const type 'const std::array<int, 5>' without a user-provided default constructor
我想为我实现的类实现同样的功能,但现在:

Array<int,5> a1;
Array<int,5> a1{};
const Array<int,5> a1;
const Array<int,5> a1{};

但是,即使是第三次初始化也可以工作,因为我只是像这样重写了默认构造函数:

Array() = default;

我在网上看到一些建议使用的解决方案:

Array() const = delete;

但这也是“语法上”不正确的。构造函数上不允许使用Const限定符。
有办法解决吗?

tvz2xvvm

tvz2xvvm1#

const和非const对象之间通常不可能有不同的初始化行为。没有办法在上面重载构造函数。
std::array是该规则的唯一例外,它的存在纯粹是为了确保用户不会意外地默认初始化一个对象到一个不确定的状态,而这个状态永远不会被修改为可用的状态(因为const),这基本上总是一个错误。
您可以找到此例外的规则,例如:在cppreference。如果类型不是 const-default-constructible,则会出现异常。
使类类型成为非 const-default-constructible,同时仍然是 default-constructible 的唯一方法是

  • 依赖于隐式的默认构造函数(基本上是通过使类聚合),或者像你展示的那样默认它,
  • 故意让类的一个成员被默认的默认构造函数留在一个不确定的状态(例如,没有默认初始化器的int

std::array<int,5>满足这一点,因为std::array始终是聚合的,并且有一个int数组作为成员,隐式默认构造函数将其保留在不确定状态。
例如,对于std::array<std::string, 5>,这种const的差异不会出现,因为std::string的数组不会被隐式默认构造函数留在不确定状态。
通常没有什么好的理由故意让成员保持未初始化,所以我不建议尝试这样做。这个例外规则的存在纯粹是为了避免犯一些未初始化的错误。

lf3rwulv

lf3rwulv2#

不,对象在它们的构造函数或析构函数中不是const,因为const构造函数可以做的很少。

相关问题