【问题标题】:How can a C++11 array not store its size?C++11 数组如何不存储它的大小?
【发布时间】:2015-11-29 23:18:09
【问题描述】:

来自cplusplus.com

在内部,数组除了包含的元素之外不保留任何数据(甚至不保留它的大小,它是模板参数,在编译时固定)。

我理解这意味着使用array 类似于在同一范围内使用int[]sizeof。但是这段代码是有效的还是依赖于未定义的行为?

class A {
    array<int, 10> arr;
    void setArr() {
        for (int& i : arr)
            i = 42;
    }
    void printArr() {
        for (int i : arr)
            cout << i << endl;
    }
};

编译器如何知道何时停止 foreach 而不将数组大小存储在堆或堆栈上?我运行它,代码有效。

【问题讨论】:

标签: c++ arrays c++11


【解决方案1】:

这是在说更多的东西,而你的引文中有回应:

[...] 甚至它的大小,它是一个模板参数,在编译时固定 [...]

例如,下面的代码也是合法的:

template<int N>
struct C {
    int size() { return N; }
};

如您所见,这里我们也这样做,并且 N 无论如何都不会保留,但它以 一个模板参数而闻名,在编译时固定

同样适用于模板类std::array,它接受定义其大小的模板参数。因此,size 在编译时是已知的(并且是固定的),它隐含地是生成类型的一部分,即使在运行时没有保留额外的空间。

编辑(根据 cmets)

当然,您不能在运行时通过简单地调用其中一个方法来更改此类数组的大小。如here所述:

std::array 是一个封装固定大小数组的容器。

另外,动态改变它的大小是没有意义的,因为它不再与定义实际大小的模板参数保持一致。因此,响应显然是:,您无法更改其大小(当然,即使您可以使用该数组填充另一个大小不同的数组)。

但是,您有很多好处:

该结构将 C 样式数组的性能和可访问性与标准容器的优点结合在一起,例如知道自己的大小、支持赋值、随机访问迭代器等。

由您决定是否值得使用它来代替普通的 C 样式数组。这主要取决于你面临的问题,所以我不能这么说。

【讨论】:

  • 所以实际上,长度是类型的一部分。这与 C 样式数组完全不同。使用这个数组,我不能用不同大小的数组替换它的值,因为它也会是不同的类型。
  • @ytoledano C 样式数组长度也是 C 样式数组类型的一部分
【解决方案2】:

当我们说 std::array存储它的大小时,我们的意思是它不保留内存来存储它的大小在运行时.

因为你说std::array&lt;int, 10&gt;,编译器知道数组的大小是10,所以它可以正确实现std::array::end。使用它,基于范围的 for 循环知道何时停止。

【讨论】:

    【解决方案3】:

    标准类std::array 具有成员函数beginend,它们返回指向数组的第一个元素和最后一个实际元素之后的位置的迭代器。

    iterator begin() noexcept;
    const_iterator begin() const noexcept;
    iterator end() noexcept;
    const_iterator end() const noexcept;
    

    当执行基于范围的 for 语句时,编译器会在名称 beginend 中搜索类并使用它们来设置有效范围。

    例如这个循环

    for (int i : arr)
        cout << i << endl
    

    实际上在内部被编译器替换为下面的循环

    for ( auto first = arr.begin(), last = arr.end(); first != last; ++first )
    {
        int i = *first;
        cout << i << endl;
    }
    

    因为类是这样声明的

    template <class T, size_t N >
    struct array;
    

    那么在类定义值N里面,数组中的元素个数,可以被类的其他成员接受,包括成员函数end()

    【讨论】:

      猜你喜欢
      • 2011-05-30
      • 2019-07-19
      • 2020-07-23
      • 1970-01-01
      • 1970-01-01
      • 2019-02-03
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多