在使用C数组的情况下,简单地命名数组与写&foo[0]
差不多有50年的历史。
在我正在处理的项目中,从C样式数组转换为std :: array <>时,出现的绝大多数“错误”是由于C数组的上述属性所致。
在所有情况下,解决方案都是微不足道的,只需追加.data()
。但是我想到精心设计的operator T*
应该可以直接解决此问题。
无法创建此运算符有任何技术原因吗?
答案 0 :(得分:5)
C样式的数组是大小合适的结构。您可以通过各种方式获得数组的编译时大小。但是,当数组衰减为指针时,您将失去编译时大小调整信息。即使参数是“数组”类型,它实际上仍然只是没有大小信息的指针。如果将数组作为函数参数(template<size_t S> void func(T(¶m)[S])
)传递,则可以使用模板编程来保留大小,仅此而已。
许多C ++程序员认为数组对指针的这种隐式衰减是C样式数组中的设计缺陷。确实,有损转换很可能不是应该隐含的转换,这并非不合理。鉴于std::array
试图修复尽可能多的C型数组缺陷,允许它隐式衰减为指针将产生反效果。
相比之下,C++20's std::span
type提供了std::array
(以及C样式数组,等等)的隐式转换。原因是这样的转换保留了信息:指针以及大小。确实,转换甚至可以保留该大小的编译时性质。
无法创建此运算符有任何技术原因吗?
“ 不能不能”?不。
答案 1 :(得分:1)
data()使其在多个STL容器中具有相似的接口。例如,std :: string和std :: vector也提供data(),它提供了实际数据缓冲区的地址。因此,std :: array接口旨在匹配该接口。您建议的Operator()是完全不同的方式,并且似乎并非绝对合适。正如上面的评论者还提到的那样,更合适的是运算符T *(),但这仍然不是STL设计人员喜欢的方式-他们引入了data()。为什么?也许是因为它更具可读性。
答案 2 :(得分:0)
此运算符不存在是有充分的理由吗?
如果您要说为什么没有operator T*()
来自动提供演员表,则(多个)潜在原因之一就是自动演员表的想法。
也许使用std::array
来使用operator T*()
来正确编译代码会很方便,而您却可以使用没有错误构建的程序。但是,这有一些含义:
1)对operator T*()
的调用是程序员可能不希望看到的潜在运行时成本,而只是随行而去。在C ++中,目标是仅支付所需的费用,而让转换运算符只是强加自己就违背了这个想法。
2)operator T*()
和一般的转换运算符可能会隐藏错误或
由于程序员不了解其用法,因此正在运行的代码中出现瓶颈。
以我的经验,请问一个代码基础上满是强制转换运算符的程序员,实际上是在调用什么函数,而且不止一次,他们不确定他们的代码采用的是什么路径,或者只是完全错误(并且直到他们参加调试会话并看到被看似无辜的转换操作员正在做的所有曲折才意识到这一点。
因此,对于程序员来说,明确地希望通过调用诸如data()
之类的函数而不是利用他们可能没有意识到的operator T*()
来“转换”数据被认为更加安全。 。
答案 3 :(得分:-2)
致电data()
是您应避免的事情。拥有此功能可能会很有用(例如,在我们的示例中,迁移代码或优化代码处理内脏),但是它违背了std::array
提供的安全网。
std::array<int, 2> a{1,2};
auto* ptr = a.data();
std::cout << ptr[2]; // boom
带走安全网的东西应该是明确的。