我正在写一个std::array
类作为一个小练习,在此过程中我发现std::array
不实现operator->
。因此,对于数组,允许以下操作
struct S { int s; };
S c[2];
c->s = 2;
但对于std::array
,这是不可能的
struct S { int s; };
std::array<S,2> cpp;
// cpp->s = 2; // does not compile
使得std::array
与c数组不完全兼容。这个决定是有原因的吗?
(我预计会有严厉的反应,但我很惊讶他们来得如此之快)
显然,正如我们所知道的,数组不是指针,只是衰变为指针。c++的问题不在于它们会衰减,而在于它们会自动衰减。如果有人故意为std::array
使用->
语法,这很可能是糟糕的设计,但不是问题。
即使有operator->
,std::array
在c++中也会像一等公民一样(这是一个数组)。
c++并不是一种不让用户受到任何伤害的语言。
c->s
可以工作,因为像c[2]
这样的原始数组,会自动将衰变成表达式中的指针。
所以c->s
等于c[0].s
。
像std::array
这样的对象不会衰变为指针,也不会提供->
或T*
的重载,因此cpp->s
不能工作。
std::array
[is]不完全兼容c数组
幸运的是不!它是一个类似数组的对象,解决了许多与原始数组相关的问题。
访问数组的第一个元素,如c->s
,可能很好,很简洁,但它的可读性是有问题的,事实上,许多人认为数组衰减是一个问题,而不是一个特性。
CppCoreGuidelines也承认数组到指针的衰减是一个问题领域:
理想情况下,程序应该是完全静态(编译时)类型的安全的。不幸的是,这是不可能的。问题:
工会
- 投
<- 阵列衰变/strong>
<- 范围错误/gh>
- 缩小转换
std::array
通过禁止它来解决源自C的特性。
c++并不是一门不让用户受到任何伤害的语言…
正确的。正如他们所说,"当你的锤子是c++时,一切都变成了大拇指"。但这并不意味着我们不能做任何事情,一次解决一个问题。这就是std::array
对原始数组的操作,std::unique_ptr
对拥有指针的操作,nullptr
对NULL
的操作,等等。
为什么没有操作符->在std::数组
因为数组不是间接的形式,数组也没有成员,所以提供间接的成员访问操作符没有什么意义。
使用操作符→使用数组是非常容易误导的(在我看来),它只作为数组到指针衰减的副作用。~使用std::array
的首要原因有50%是为了避免无意的数组到指针的衰减。
你可能想说
c->s = 2;
代替c->x
。当将c
声明为数组时,变量c
只是指向该数组的第一个元素c[0]
的指针,在您的示例中,这是一个结构体。对指针c->s
应用操作符->
与c[0].s
相同。当使用std::array
时,变量cpp
不表示指向第一个元素的指针。因此,箭头操作符在这里没有任何意义。