为什么 std::array 中没有 operator->
Why there is no operator-> in std::array
我正在写一个 std::array
class 作为一个小练习,期间我发现 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++ 中的第一个 class-citizien(不是数组)。
C++ 不是一种可以防止用户受到任何伤害的语言。
Why there is no operator-> in std::array
因为数组不是间接形式,数组也没有成员,所以提供间接成员访问运算符意义不大。
将 operator-> 与数组一起使用非常具有误导性(在我看来),它仅作为数组到指针衰减的副作用起作用。首先使用 std::array
的约 50% 的原因是为了避免无意的数组到指针衰减。
c->s
之所以有效,是因为像 c[2]
这样的原始数组会自动 衰减 到表达式中的指针。
所以 c->s
等价于 c[0].s
.
诸如 std::array
之类的对象不会衰减为指针并且不提供 ->
或 T*
重载,因此 cpp->s
不起作用。
std::array
[is] not fully compatible to a C-array
幸运的是没有!它是一个类似数组的 object,解决了许多与原始数组相关的问题。
像c->s
这样访问数组的第一个元素可能简洁明了,但它的可读性值得怀疑,事实上很多人认为数组衰减是一个问题而不是一个特性。
CppCoreGuidelines admits array-to-pointer-decay 也是一个问题领域:
Ideally, a program would be completely statically (compile-time) type
safe. Unfortunately, that is not possible. Problem areas:
- unions
- casts
- array decay
- range errors
- narrowing conversions
std::array
通过禁止它来解决源于 C 的特质。
C++ is not a language where the user shall be prevented from every harm ...
没错。正如他们所说,“当你的锤子是 C++ 时,一切都变成拇指”。
但这并不意味着我们对此无能为力,一次解决一个问题领域。这就是 std::array
对原始数组的作用,std::unique_ptr
对拥有指针的作用,nullptr
对 NULL
的作用,等等
你可能想说
c->s = 2;
而不是 c->x
。当 c
声明为数组时,变量 c
只是指向该数组的第一个元素 c[0]
的指针,在您的例子中是一个结构。将运算符 ->
应用于该指针 c->s
与 c[0].s
相同。
使用 std::array
时,变量 cpp
不代表指向第一个元素的指针。因此箭头运算符在这里没有任何意义。
我正在写一个 std::array
class 作为一个小练习,期间我发现 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++ 中的第一个 class-citizien(不是数组)。
C++ 不是一种可以防止用户受到任何伤害的语言。
Why there is no operator-> in std::array
因为数组不是间接形式,数组也没有成员,所以提供间接成员访问运算符意义不大。
将 operator-> 与数组一起使用非常具有误导性(在我看来),它仅作为数组到指针衰减的副作用起作用。首先使用 std::array
的约 50% 的原因是为了避免无意的数组到指针衰减。
c->s
之所以有效,是因为像 c[2]
这样的原始数组会自动 衰减 到表达式中的指针。
所以 c->s
等价于 c[0].s
.
诸如 std::array
之类的对象不会衰减为指针并且不提供 ->
或 T*
重载,因此 cpp->s
不起作用。
std::array
[is] not fully compatible to a C-array
幸运的是没有!它是一个类似数组的 object,解决了许多与原始数组相关的问题。
像c->s
这样访问数组的第一个元素可能简洁明了,但它的可读性值得怀疑,事实上很多人认为数组衰减是一个问题而不是一个特性。
CppCoreGuidelines admits array-to-pointer-decay 也是一个问题领域:
Ideally, a program would be completely statically (compile-time) type safe. Unfortunately, that is not possible. Problem areas:
- unions
- casts
- array decay
- range errors
- narrowing conversions
std::array
通过禁止它来解决源于 C 的特质。
C++ is not a language where the user shall be prevented from every harm ...
没错。正如他们所说,“当你的锤子是 C++ 时,一切都变成拇指”。
但这并不意味着我们对此无能为力,一次解决一个问题领域。这就是 std::array
对原始数组的作用,std::unique_ptr
对拥有指针的作用,nullptr
对 NULL
的作用,等等
你可能想说
c->s = 2;
而不是 c->x
。当 c
声明为数组时,变量 c
只是指向该数组的第一个元素 c[0]
的指针,在您的例子中是一个结构。将运算符 ->
应用于该指针 c->s
与 c[0].s
相同。
使用 std::array
时,变量 cpp
不代表指向第一个元素的指针。因此箭头运算符在这里没有任何意义。