当我像这样在“LevelEditor”类定义中声明“Level”对象时,一切正常:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
}
//...
private:
//...
Level level = Level(50, 50);
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
但是当我像这样在“LevelEditor”构造函数中声明“Level”对象时,出现堆栈溢出:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
//NOTE: width and height both equal 50
level = Level(width, height);
}
//...
private:
//...
Level level;
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
这让我想知道在类定义中声明变量和在构造函数中声明变量除了定义变量的时间之外还有什么区别。知道原因可能是什么吗?以及如何在构造函数中声明“Level”对象而不必在堆上放置任何东西?
编辑: “级别”类定义,以防有帮助:
class Level
{
public:
Level(int w, int h)
{
Worldwidth = w;
Worldheight = h;
for (unsigned int y = 0; y < Worldheight; y++)
{
for (unsigned int x = 0; x < Worldwidth; x++)
{
grid[x][y] = -1;
}
}
}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
int grid[300][300];
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
最佳答案
您的代码存在多个问题。我将尝试解决 stack overflow
错误。另一个问题是你的 Level
类不可安全复制——这可以通过使用 std::unique_ptr
等智能指针来解决。和 std::shared_ptr
.
首先,您的类(class)使用 300 x 300 的 T
数组,在一种情况下,T
是 WorldSprite*
另一个是int
.声明为成员的这种大小的数组将使包含它们的每个对象的大小膨胀到数百 KB。这有时会对堆栈造成影响。
所以你应该删除这些定义,而是使用 std::vector
.
#include <vector>
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader) :
tile(w,std::vector<WorldSprite*>(h))
editing(true), width(w), height(h)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y,
tileWidth, tileHeight, shader);
}
level = Level(width, height);
}
private:
Level level;
int width, height;
std::vector<std::vector<WorldSprite*>> tile;
bool editing;
};
这是 Level
具有相同类型更改的类:
#include <vector>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int> >grid;
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
注意vector代替了array,会使用堆内存来初始化。在Level
类,我们初始化 vector 并将所有条目设置为 -1
在 vector 构造函数的一次调用中。
这不会将对象的大小增加到非常高的原因是 vector 将在堆上创建其数据(除非您有某种自定义分配器从另一个来源获取内存)。因此,您的类的大小将是合理的(可能小于 100 字节)。
另一个问题是您的 Level
类不可安全复制(LevelEditor
也不是,但我会保留它,因为可以完成相同的一组更改)。
问题出在这一行:
level = Level(width, height);
这一行的问题是会调用赋值运算符,可能会调用拷贝构造函数。如果你看看你的 Level
类,它有一个析构函数,可以从包含指针的 vector 中删除所有指针。如果您复制 Level
,这将是灾难性的对象,因为由于临时对象被销毁,您将销毁所有数据。
如果没有意义的话Level
实际上拥有指针,归结为“谁是最后一个站着的人就是所有者”,您实际上将在 Level
之间共享指针实例(这就是它被称为 shared_ptr 的原因)那么你可以使用这个解决方案:
#include <vector>
#include <memory>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int>> grid;
std::vector<std::shared_ptr<Tile>> tiles;
std::vector<std::shared_ptr<Entity>> entities;
};
请注意没有析构函数代码——不需要任何析构函数代码。删除全部由 shared_ptr
完成,因此您无事可做——一切都在管理之中。将会发生的是最后一个 Level
与您共享指针的那个被销毁将进行实际删除。所以当这一行完成时
level = Level(width, height);
Level
的复制物体在内部上下颠簸shared_ptr
的引用计数,使您的引用计数为 1(即 level
符号左侧的最后一个 =
)。
请参阅此处了解 std::shared_ptr
的用法: http://en.cppreference.com/w/cpp/memory/shared_ptr
请注意,您可能需要使用 std::unique_ptr
如果所有权是一个问题。我建议您在 SO 中搜索 std::unique_ptr
的用法.我给你看了std::shared_ptr
因为此时它是最直接的(但同样,可能无法满足您的所有需求 - YMMV)。
关于c++ - 在类定义中与在构造函数中将对象声明到堆栈上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29158466/