对于具有固定的运行时确定的大小的数组,是否有标准的C ++类?

αλε*_*λυτ 4 c++ arrays c++20

我需要一个运行时大小已知的容器,而无需调整大小。std::unique_ptr<T[]>会很有用,但没有封装的size成员。同时std::array只适用于编译类型的大小。因此,我需要这些类的某种组合,而没有/最小的开销。

是否有满足我需求的标准类,也许在即将发布的C ++ 20中有?

Gui*_*cot 11

使用std::vector。这是STL中运行时大小的数组的类。

它允许您调整大小或将元素推入其中:

auto vec = std::vector<int>{};

vec.resize(10); // now vector has 10 ints 0 initialized
vec.push_back(1); // now 11 ints
Run Code Online (Sandbox Code Playgroud)

评论中指出的一些问题:

向量的接口过多

也是如此std::arraystd::array包括运算符在内,您有20多个功能。

只是不要使用您不需要的东西。您无需为不使用的功能付费。它甚至不会增加您的二进制文件大小。

向量将强制初始化项目的大小。据我所知,它不允许operator[]用于索引> = size(尽管调用reserve)。

这不是要使用的方式。保留时,应使用resize或通过将向量推入向量来调整向量的大小。您说vector将强制将初始化元素放入其中,但问题是您无法调用operator=未构造的对象,包括int。

这是使用reseve的示例:

auto vec = std::vector<int>{};

vec.reseve(10); // capacity of at least 10
vec.resize(3); // Contains 3 zero initialized ints.

// If you don't want to `force` initialize elements
// you should push or emplace element into it:

vec.emplace_back(1); // no reallocation for the three operations.
vec.emplace_back(2); // no default initialize either.
vec.emplace_back(3); // ints constructed with arguments in emplace_back
Run Code Online (Sandbox Code Playgroud)

请记住,这种分配和用例的可能性很大,编译器可能会完全忽略向量中元素的构造。您的代码可能没有任何开销。

如果您的代码受非常精确的性能规范的约束,我建议进行测量剖析。如果您没有这样的规范,则很可能是过早的优化。内存分配的成本完全无法衡量初始化元素所需的时间。

程序的其他部分可能经过重构以获得比普通初始化所能提供的性能高得多的性能。实际上,采用这种方式可能会阻碍优化并降低程序速度。

  • @αλεχολυτ:定义“仅初始化说第5个元素”。对象必须经过某种形式的构建,即使最终归结为未初始化状态也是如此。保留部分中的内存中没有对象,无论是否初始化。并且如果第5个元素之前的空间中没有对象,则它不是10个元素的数组。 (3认同)
  • @αλεχολυτ确定要的东西明智吗?您写了`int a [10]; a [5] = 42;`; 您如何跟踪只有a [5]初始化的事实,并避免读取其他索引(未定义的行为)? (2认同)

ein*_*ica 5

使用std::unique_ptr<T[]>您建议的类似方式分配内存,但要使用它-使用原始指针和元素数量构造一个std::span(在C ++ 20中;gsl::span在C ++ 20之前),然后将span传递给(按值; span为引用类型)。跨度将为您提供容器的所有优势:大小,迭代器,适用范围,作品。

#include <span>
// or:
// #include <gsl/span>

int main() {

    // ... etc. ...

    {
        size_t size = 10e5;
        auto uptr { std::make_unique<double[]>(size) };
        do_stuff_with_the_doubles(std::span<int> my_span { uptr.get(), size });
    }

    // ... etc. ...
}
Run Code Online (Sandbox Code Playgroud)

有关跨度的更多信息,请参见:

什么是“跨度”?何时应使用?

  • 请注意,在这种方法中,数据的所有权和有关其跨度的信息仍然分开保存…… (3认同)

Cal*_*eth 5

使用std::vector. 如果您想消除更改其大小的可能性,请将其包裹起来。

template <typename T>
single_allocation_vector : private std::vector<T>, public gsl::span<T>
{
    single_allocation_vector(size_t n, T t = {}) : vector(n, t), span(vector::data(), n) {}
    // other constructors to taste
};
Run Code Online (Sandbox Code Playgroud)