关于 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 works 和 std::array
s.
问题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());
。
** 这个问题经过大量编辑以提供(在了解解决方案之后)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 works 和 std::array
s.
问题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());
。