std::vector<unique_ptr<class T>> 的动态初始化
dynamical initialization of std::vector<unique_ptr<class T>>
我有一个 class 网格声明如下:
Grid.h
#ifndef DATATEST_GRID_H
#define DATATEST_GRID_H
#include <memory>
#include <vector>
#include "Position.h"
class Grid
{
public:
Grid(int length_x, int length_y);
~Grid();
Position *at(int x, int y);
void printGrid();
private:
int length_x, length_y;
std::vector<std::unique_ptr<Position>> grid;
};
#endif
它最重要的成员变量是vector<unique_ptr<Position>>
,我用它来模拟一个二维数组,其大小在运行时确定。 Position 的 class 声明如下:
Position.h
#ifndef DATATEST_POSITION_H
#define DATATEST_POSITION_H
#include <memory>
#include <string>
class Position {
public:
Position(int x, int y);
~Position();
std::string toString();
int getX() { return x; };
int getY() { return y; };
private:
int x, y;
};
#endif
在网格的构造函数中,我想创建所需数量的位置并将它们添加到 vector<unique_ptr<Position>>
。
Grid.cpp
#include "Grid.h"
#include <iostream>
#include <memory>
#include <vector>
#include "Position.h"
Grid::Grid(int length_x, int length_y)
: length_x(length_x), length_y(length_y)
{
grid.resize(length_x * length_y);
for (int x = 0; x < length_x; x++) {
for (int y = 0; y < length_y; y++) {
/* Option 1 */
std::unique_ptr<Position> temp = std::make_unique<Position>(x, y);
grid.push_back(std::move(temp));
/* Option 2 */
// std::unique_ptr<Position> temp = std::make_unique<Position>(x, y);
// grid.emplace_back(std::move(temp));
/* Option 3 */
// grid.push_back(std::make_unique<Position>(x, y));
/* Option 4 */
// grid.emplace_back(std::make_unique<Position>(x, y));
}
}
}
Grid::~Grid()
{
grid.clear();
}
Position *Grid::at(int x, int y)
{
if (x < 0 || x >= length_x || y < 0 || y >= length_y) {
return nullptr;
}
else {
return grid.at(x * (length_y) + y).get();
}
}
void Grid::printGrid()
{
for (int i = 0; i < grid.size(); i++) {
std::cout << grid.at(i)->toString() << std::endl;
}
}
我正在通过为每个 unique_ptr<Position>
调用 Position::toString 并将结果打印到控制台来测试访问。
Position.cpp
#include "Position.h"
#include <string>
Position::Position(int x, int y)
: x(x), y(y)
{
}
Position::~Position()
{
}
std::string Position::toString()
{
return "Position(" + std::to_string(x) + ", " + std::to_string(y) + ")";
}
最后,主要功能:
Main.cpp
#include "Grid.h"
#include "Position.h"
int main()
{
Grid g(2, 2);
g.printGrid();
return 0;
}
无论我以何种方式填充 vector<unique_ptr<Position>>
,我总是会收到以下错误:
CombatSim.exe 中 0x0087D8A3 处的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。
CombatSim.exe 中 0x0087D8A3 处的未处理异常:0xC0000005:读取位置 0x00000000 的访问冲突。
据我所知,我可能遇到以下四个问题之一:
1) 我将创建的 Position 对象的 unique_ptr 添加到向量中不正确
2) 我使用了错误的方法来动态创建 Position 对象。
3) 以上皆是。
4)我不知道的事情。
调整网格大小似乎首先会插入 length_x * length_y
个唯一指针,这些指针都指向 0
。您的 push_back
应该没问题,但您的真实元素从向量中的位置 length_x * length_y
开始。我想删除行
grid.resize(length_x * length_y);
应该可以解决问题。也许其他人可以解释为什么会这样。
如果您之后要 push_back
那些 n 个元素,请使用 std::vector::reserve(n)
而不是 std::vector::resize(n)
。
resize
将 填充 具有初始化对象的向量,因此 vector.size()
之后将是 n .
reserve
只会为所有 n 元素保留足够的 space,但不会插入任何对象。
我有一个 class 网格声明如下:
Grid.h
#ifndef DATATEST_GRID_H
#define DATATEST_GRID_H
#include <memory>
#include <vector>
#include "Position.h"
class Grid
{
public:
Grid(int length_x, int length_y);
~Grid();
Position *at(int x, int y);
void printGrid();
private:
int length_x, length_y;
std::vector<std::unique_ptr<Position>> grid;
};
#endif
它最重要的成员变量是vector<unique_ptr<Position>>
,我用它来模拟一个二维数组,其大小在运行时确定。 Position 的 class 声明如下:
Position.h
#ifndef DATATEST_POSITION_H
#define DATATEST_POSITION_H
#include <memory>
#include <string>
class Position {
public:
Position(int x, int y);
~Position();
std::string toString();
int getX() { return x; };
int getY() { return y; };
private:
int x, y;
};
#endif
在网格的构造函数中,我想创建所需数量的位置并将它们添加到 vector<unique_ptr<Position>>
。
Grid.cpp
#include "Grid.h"
#include <iostream>
#include <memory>
#include <vector>
#include "Position.h"
Grid::Grid(int length_x, int length_y)
: length_x(length_x), length_y(length_y)
{
grid.resize(length_x * length_y);
for (int x = 0; x < length_x; x++) {
for (int y = 0; y < length_y; y++) {
/* Option 1 */
std::unique_ptr<Position> temp = std::make_unique<Position>(x, y);
grid.push_back(std::move(temp));
/* Option 2 */
// std::unique_ptr<Position> temp = std::make_unique<Position>(x, y);
// grid.emplace_back(std::move(temp));
/* Option 3 */
// grid.push_back(std::make_unique<Position>(x, y));
/* Option 4 */
// grid.emplace_back(std::make_unique<Position>(x, y));
}
}
}
Grid::~Grid()
{
grid.clear();
}
Position *Grid::at(int x, int y)
{
if (x < 0 || x >= length_x || y < 0 || y >= length_y) {
return nullptr;
}
else {
return grid.at(x * (length_y) + y).get();
}
}
void Grid::printGrid()
{
for (int i = 0; i < grid.size(); i++) {
std::cout << grid.at(i)->toString() << std::endl;
}
}
我正在通过为每个 unique_ptr<Position>
调用 Position::toString 并将结果打印到控制台来测试访问。
Position.cpp
#include "Position.h"
#include <string>
Position::Position(int x, int y)
: x(x), y(y)
{
}
Position::~Position()
{
}
std::string Position::toString()
{
return "Position(" + std::to_string(x) + ", " + std::to_string(y) + ")";
}
最后,主要功能:
Main.cpp
#include "Grid.h"
#include "Position.h"
int main()
{
Grid g(2, 2);
g.printGrid();
return 0;
}
无论我以何种方式填充 vector<unique_ptr<Position>>
,我总是会收到以下错误:
CombatSim.exe 中 0x0087D8A3 处的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。 CombatSim.exe 中 0x0087D8A3 处的未处理异常:0xC0000005:读取位置 0x00000000 的访问冲突。
据我所知,我可能遇到以下四个问题之一:
1) 我将创建的 Position 对象的 unique_ptr 添加到向量中不正确
2) 我使用了错误的方法来动态创建 Position 对象。
3) 以上皆是。
4)我不知道的事情。
调整网格大小似乎首先会插入 length_x * length_y
个唯一指针,这些指针都指向 0
。您的 push_back
应该没问题,但您的真实元素从向量中的位置 length_x * length_y
开始。我想删除行
grid.resize(length_x * length_y);
应该可以解决问题。也许其他人可以解释为什么会这样。
如果您之后要 push_back
那些 n 个元素,请使用 std::vector::reserve(n)
而不是 std::vector::resize(n)
。
resize
将 填充 具有初始化对象的向量,因此 vector.size()
之后将是 n .
reserve
只会为所有 n 元素保留足够的 space,但不会插入任何对象。