作为练习,我实现了一个名为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限定符。
有办法解决吗?
2条答案
按热度按时间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
的数组不会被隐式默认构造函数留在不确定状态。通常没有什么好的理由故意让成员保持未初始化,所以我不建议尝试这样做。这个例外规则的存在纯粹是为了避免犯一些未初始化的错误。
lf3rwulv2#
不,对象在它们的构造函数或析构函数中不是
const
,因为const
构造函数可以做的很少。