我认为我对C++相当了解,我正在考虑实现一个比“玩具”程序更大的东西。我知道堆栈和堆内存和RAII成语之间的区别。
假设我有一个简单的类点
class point {
public:
int x;
int y;
point(int x, int y) : x(x), y(y) {}
};我总是在堆栈上分配点,因为对象很小。因为在64位机器sizeof(point) == sizeof(void*)上,如果a是正确的,我会更进一步,默认情况下传递值。
现在让我们假设一个更复杂的类战场,我想在类游戏中使用它。
class battlefield {
public:
battlefield(int w, int h, int start_x, int start_y, istream &in) {
// Complex generation of a battlefield from a file/network stream/whatever.
}
};因为我非常喜欢RAII和对象离开作用域时的自动清理,所以我很想在堆栈上分配战场。
game::game(const settings &s) :
battlefield(s.read("w"), s.read("h"), gen_random_int(), gen_random_int(), gen_istream(s.read("level_number"))) {
// ...
}但我现在有几个问题:
我看到了解决这个问题的两种方法:
我希望你能看到我正在考虑的问题。我遇到的一些问题是:
发布于 2012-06-23 12:45:28
您可以让您的战场由设置构建:
explicit battlefield(const settings& s);或者,为什么不为您的battlefield创建一个工厂函数?
例如。
battlefield CreateBattlefield(const settings& s)
{
int w = s.read("w");
int h = s.read("w");
std::istream& in = s.genistream();
return battlefield(w, h, gen_random_int(), gen_random_int(), in);
}
game::game(const settings &s) :
battlefield(CreateBattlefield(s)) {
// ...
}发布于 2012-06-23 12:36:16
但是这种方法有一个问题,就是我有一个半初始化的对象,也就是一个违反RAII-成语的对象。
那不是莱伊。概念是使用对象来管理资源。当您获得堆内存、信号量、文件句柄等资源时,必须将所有权传递给资源管理类。这就是C++中智能指针的意义所在。如果希望拥有对象的唯一所有权,则必须使用unique_ptr;如果希望拥有多个指针,则必须使用shared_ptr。
或者我在游戏构造函数堆上分配战场。但是我必须注意构造函数中的异常,我必须注意析构函数删除战场。
如果构造函数抛出异常,则不会调用对象的析构函数,您可能会以半熟对象结束。在这种情况下,您必须记住在抛出异常之前在构造函数中做了哪些分配,并释放所有这些。同样,智能指针将有助于资源的自动清理。参见此常见问题
堆上分配了哪些对象,堆栈上分配了哪些对象?为什么?
尽可能地在堆栈中分配对象。然后,您的对象只有在该块的范围内才有生命。如果有这样的情况无法进行堆分配-例如:您只知道运行时的大小,对象的大小太大,不能放在堆栈上。
https://stackoverflow.com/questions/11169366
复制相似问题