关于 std::vector<T> object[arraySize] 的可能误解

Possible misunderstanding regarding std::vector<T> object[arraySize]

** 这个问题经过大量编辑以提供(在了解解决方案之后)MCVE 格式的问题示例。用于解决问题的 MCVE 可以在 this ideone link 找到。 ** (如果 ideone.com 删除了 posts,有人告诉我!)

对此 post 的评论包括 link 到 rextester link,其中包含@dyp 提供的编辑(尽管我不知道这会如何随时间变化)* *

template <typename T, size_t fD, size_t mD>
class Field
{
public:
    // Constructor - the problem turned out to be here
    Field(const Mesh<mD>& mesh, const std::string &fileName):
        fileName_(fileName),
        mesh_(mesh)
    {
        for (size_t d=0; d<fD; d++) {
            field_[d].reserve(mesh.numCellS());
        }
    }

    // Copy constructor - maybe I've written this horribly?
    Field(const Field<T,fD,mD>& refToCopy, const std::string &name):
        fileName_(name),
        mesh_(refToCopy.mesh_)
    {
        for (size_t d=0; d<fD; d++) {
            field_[d] = refToCopy.field_[d];
        }
    }

    // Const Accessors
    const std::vector<T> &x() const { return field_[0]; }
    // some checking that fD is large enough
    const std::vector<T> &y() const { return field_[1]; }
    // Repeated, non-const.

    void setZero();
    void setFixed(const T &val);

private:
    std::vector<T> field_[fD];
}

template<typename T, size_t fD, size_t mD>
void Field<T,fD,mD>::setZero()
{
    setFixed(T(0));
}

// This might need to be explicit.
// Currently, 'a' can be converted for Field<double, D>
template<typename T, size_t fD, size_t mD>
void Field<T,fD,mD>::setFixed(const T &val)
{
    for (size_t d=0; d<fD; d++) {
        std::fill(field_[d].begin(), field_[d].end(), val);
    }
}

当我尝试访问复制字段(不是从头构建的字段)的值时,出现段错误。将 std::cout << "field_[" << d << "][" << i << "] = " << field_[d][i] 放在复制构造函数中 i 的循环中也会引发此问题(没有任何输出,因此大概是 i 的第一个值...

一个示例调用可能是:

Field<double, 2, 2> fieldA(constructor arguments);
fieldA.setZero(); // <- This is what I misunderstood
Field<double, 2, 2> fieldB(fieldA, "copyOfFieldA");
std::cout << "fieldB.x()[5] = " << fieldB.x()[5] << std::endl;

我哪里做错了?我应该改用 std::array<std::vector<T>> 吗?这是访问字段的无效方式吗?或者我的复制构造函数只是垃圾(疑似案例)。

总结一下评论,我的理解是字段的初始化存在问题(特别是每个维度中向量元素的分配+初始化)。

您可以找到完整的 运行 代码 here

问题 1

声明为 Type x[N] 的固定大小数组无法使用语法 x(y) 进行复制初始化。尽管请注意 it worksstd::arrays.

问题2

reserve 只影响标准容器的容量,不影响其大小。特别是,在保留但未调整大小的容器上使用 std::fill 不会执行任何操作。

除了迭代固定大小数组的每个元素以手动调整(或assign)大小外,这里没有解决方法。


无论如何,我建议使用 C++11 的 std::array;没有开销,您的代码将更清晰,您将能够更轻松地从移动操作中受益。

@dyp 提供的答案。发帖是因为评论表明他很忙。

构造函数使用field_[d].reserve(mesh.numCells());

为条目保留 内存,但不创建任何条目。 (这个我就知道)

fieldA.setZero() 的后续调用调用 std::fill 不会创建条目(我错过了这一点)

创建副本时,程序会尝试读取不存在的值,因为尽管已分配内存,但那里从未放置过任何值。

因此,最简单的解决方案是在 Field 构造函数中将 field_[d].reserve(mesh.numCells()); 更改为 field_[d].resize(mesh.numCells());