为什么数组的维是其类型的一部分?

时间:2019-11-21 14:47:04

标签: c++ arrays c++11

在阅读C ++ Primer书籍时,我遇到了这样的说法:“数组中元素的数量是数组类型的一部分。”所以我想用下面的代码找出答案:

#include<iostream>

int main()
{
    char Array1[]{'H', 'e', 'l', 'p'};
    char Array2[]{'P', 'l', 'e', 'a', 's', 'e'};

    std::cout<<typeid(Array1).name()<<std::endl;        //prints  A4_c
    std::cout<<typeid(Array2).name()<<std::endl;        //prints  A6_c

    return 0;
}

有趣的是,两个数组上的typeid结果表明它们有所不同。

  • 幕后发生了什么事?
  • 为什么数组必须具有包含其大小的类型?仅仅是因为它的大小不应该改变吗?
  • 这将如何影响比较数组?

只想能够深刻理解这个概念。

3 个答案:

答案 0 :(得分:20)

  

幕后发生了什么事?

根据定义,非动态分配的是同类元素的固定大小容器。 N类型的T个元素的数组作为N类型的T个对象的连续序列布置在内存中。


  

为什么数组必须具有包含其大小的类型?

我认为数组的类型不必包含它的大小-实际上,您可以使用指针来引用T对象的连续序列。这样的指针会丢失有关数组的大小信息。

但是,这是一件有用的事情。它提高了类型安全性,并在编译时对有用的信息进行了编码,可以以多种方式使用。例如,您可以使用引用数组在不同大小的数组上重载

void foo(int(&array)[4]) { /* ... */ }
void foo(int(&array)[8]) { /* ... */ }

或者将数组的大小作为常量表达式计算出来

template <typename T, std::size_t N>
constexpr auto sizeOf(const T(&array)[N]) { return N; }

  

这将如何影响比较数组?

实际上不是。

您无法以比较两个数字(例如int对象)的相同方式比较C样式的数组。您将必须编写某种词典比较,并确定这对于不同大小的集合意味着什么。 std::vector<T> provides that,并且相同的逻辑可以应用于数组。


奖金::C ++ 11及更高版本提供std::array,它是带有容器式接口的C样式数组的包装。应该首选C样式的数组,因为它与其他容器(例如std::vector<T>)更加一致,并且还支持开箱即用的lexicographical comparisons

答案 1 :(得分:8)

创建对象时分配给该对象的空间量完全取决于其类型。我所说的分配不是来自newmalloc的分配,而是分配的空间,以便您可以运行构造函数并初始化对象。

如果您将结构定义为(例如)

struct A { char a, b; }; //sizeof(A) == 2, ie an A needs 2 bytes of space

然后在构造对象时:

A a{'a', 'b'};

您可以将构造对象的过程视为一个过程:

  • 分配2个字节的空间(在堆栈上,但是对于本示例来说无关紧要)
  • 运行对象的构造函数(在这种情况下,将'a''b'复制到对象)

重要的是要注意,所需的2个字节的空间完全由对象的类型决定,函数的参数无关紧要。因此,对于数组,处理过程是相同的,除了现在所需的空间量取决于数组中元素的数量。

char a[] = {'a'}; //need space for 1 element
char b[] = {'a', 'b', 'c', 'd', 'e'}; //need space for 5 elements

因此ab的类型必须反映以下事实:a需要足够的空间来容纳1个字符,而b需要足够的空间来容纳5个字符。这确实意味着这些数组的大小不能突然改变,一旦创建了5个元素的数组,它始终是5个元素的数组。为了拥有大小可能会变化的类似“数组”的对象,您需要动态分配内存,这应该在您的书中有所涉及。

答案 2 :(得分:0)

这是运行库的内部原因。例如,如果考虑以下语句:

unsigned int i;
unsigned int *iPtr;
unsigned int *iPtrArr[2];
unsigned int **iPtrHandle;

然后清楚地知道问题出在哪里:例如,unsigned int *的地址必须与sizeof operatorunsigned int的地址有关。

对于您在此处看到的其余内容有更详细的解释,但这主要是对Kernighan和Ritchie的 C编程语言,第二版所涵盖内容的概括。打印声明的类型字符串的纯语言文本。

相关问题