字符串[]不是类型吗?

时间:2014-11-25 01:09:26

标签: c++ language-lawyer

用户发布了answer,其中写着:

  

因此,请参考Hash

void topWords(Hash const& t, std::string const& word, std::string* topA); 
     

另外,

     
      
  • string[]不是C ++中的类型
  •   
  • ...
  •   

提问者发布的原始功能如下:

void topWords(Hash t, string word, string topA[]); 

我知道在Java中,声明数组的语法是:

int[] anArray;

而在C ++中它是:

int anArray[someNumber];

我怀疑这是回答者所指的,但也许他们意味着别的东西。所以我咨询了n3337

格式化注释:省略了无关的内容,为了便于阅读添加了新行

§8.3.4[dcl.array]

  

1在声明T D中,D的格式为

     
    

D1 [常量表达式 opt ]     属性说明符-SEQ <子>选择

  
     

和声明T D1中的标识符类型是   “ derived-declarator-type-list T”,然后是标识符的类型   D的数组类型;

     

...

     

T称为数组元素类型;

     

...

     

如果存在常量表达式(5.19),则它应为a   积分常数表达式及其值应大于零。   常量表达式指定 的边界(元素数量)   in)数组。如果常量表达式的值为N,则为。{   数组有N个元素编号为0N-1,以及类型   D的标识符是“{em> derived-declarator-type-list array of N T”。

     

...

     

除非另有说明,否则如果省略常量表达式,则为类型   D的标识符是“ derived-declarator-type-list 数组   未知的T“范围,一个不完整的对象类型。类型   “{em> derived-declarator-type-list N T”数组是一种不同的类型   来自类型“ derived-declarator-type-list 未知边界的数组   T“,见3.9。

     

...

所以anArray应该是someNumber int的数组。 topA调整为pointer to std::string。我的理解在哪里失败?


为了避免使当前答案无效,我会将其作为更新发布。你们当中有些人似乎误解了我的问题的本质。我不是在询问Java vs C ++,也不是数组与指针,而是从语言律师的角度来看,为什么string[]不会被视为类型。

如果我们看一下§3.9/ 6:

  

...数组对象的声明类型可能是未知数组   大小因此在翻译单元中的某一点不完整   并在以后完成;这两个点的数组类型(“数组的数组   T“的未知范围和”N T“的数组是不同的类型。 ...... [   示例:

extern int arr[]; // the type of array is incomplete

所以arr 显然有一个类型。

5 个答案:

答案 0 :(得分:4)

您的理解似乎大多是正确的 - 因为topA是一个形式参数,其类型会从array of T调整为pointer to T。同样,anArray将是someNumber int的数组。

对于它的价值,在有限的情况下你可以在C ++中使用空括号并且仍然有一个数组,而不是一个指针。最常见的是extern声明,如:

extern int anArray[];

...将anArray声明为一个int数组,其数量在指定的位置指定。

如果有人以声明为string topA[]的参数开头,那么在大多数情况下,编译器会将其调整为string *topA you < / em>可能希望将其更改为:std::vector<std::string> &topA(或std::vector<std::string> const &topA,如果您不打算修改数组的内容。)

答案 1 :(得分:4)

string[]是一个不完整的数组类型。

可以完成不完整的数组类型:

  

C ++11§3.9/ 6
     声明的数组对象类型可能是一个未知大小的数组,因此在某一点上是不完整的   在翻译单位,稍后完成;这两个点的数组类型(“T未知范围的数组”和“N T数组”是不同的类型。

通常会发生类似

的声明
extern int x[];

在某个标题中,然后在实现文件中

int x[42];

除了因未知长度而不完整外,由于项目类型不完整,数组类型可能不完整。

struct Blah;
extern Blah x[42];

auto main() -> int {}

但是,这不允许void

的数组

顺便说一下,值得一提的是unique_ptr<T>unique_ptr<T[]>不同。后者在其支持的转换中受到限制。这是因为如果将指针转换为类型为T的数组,指向类型为T_baseT_derived的数组的指针,则为项目大小可能不同,从而导致索引(以及其他许多内容)。

答案 2 :(得分:2)

如果你继续阅读§8.3.4,我们会得到这一段(大胆强调我的):

  

数组类型的对象包含一个连续分配的非空N类型的子对象。   类型 derived-declarator-type-list NT”数组与类型 derived-declarator-type的类型不同-list 数组   未知的T 界限“,见3.9。任何类型的形式“ cv-qualifier-seq N T数组”都调整为“数组”   N cv-qualifier-seq T“,类似于”T的未知界限数组“和”T的运行时界限数组“。   可选的 attribute-specifier-seq 属于数组。

举例:

typedef int A[5], AA[2][3];
typedef const A CA; // type is “array of 5 const int”

由于标准提到了数组类型,并且显示了一个清楚地表明变量类型是数组的例子,我认为这足以证明数组通常是一种类型。这是一种奇怪的类型,不像其他基本类型那样好玩,但它仍然是一种类型。该段特别提到“T的未知界限”类型,也就是你的string[]

答案 3 :(得分:2)

extern int arr[]; // the type of array is incomplete
     

所以arr显然有一个类型。

arr有一个类型。这不会使int[]成为完整类型。 arr具有不完整的类型,直到定义了数组维度(可能在另一个TU中)。

  

[...] D的标识符的类型是“T的未知边界的derived-declarator-type-list数组”,不完整的对象类型

在此之前参考arr的具体类型(例如使用sizeof)将会出错。

答案 4 :(得分:0)

string[]是一种类型,但它是一种误导性的;你不能只复制string[]s并希望它能做你想做的事。它本质上是写string *的另一种方式。

如果您想要一个可以传递的string数组,请使用std::vector<std::string>(按值)或boost::shared_array<std::string>(按引用)或类似名称。 boost::shared_array可能最接近您对Java数组类型的期望。