首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用复杂构造函数分配对象?

如何使用复杂构造函数分配对象?
EN

Stack Overflow用户
提问于 2012-06-23 12:07:12
回答 2查看 1K关注 0票数 3

我认为我对C++相当了解,我正在考虑实现一个比“玩具”程序更大的东西。我知道堆栈和堆内存和RAII成语之间的区别。

假设我有一个简单的类点

代码语言:javascript
运行
复制
class point {
public:
    int x;
    int y;
    point(int x, int y) : x(x), y(y) {}
};

我总是在堆栈上分配点,因为对象很小。因为在64位机器sizeof(point) == sizeof(void*)上,如果a是正确的,我会更进一步,默认情况下传递值。

现在让我们假设一个更复杂的类战场,我想在类游戏中使用它。

代码语言:javascript
运行
复制
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和对象离开作用域时的自动清理,所以我很想在堆栈上分配战场。

代码语言:javascript
运行
复制
game::game(const settings &s) :
        battlefield(s.read("w"), s.read("h"), gen_random_int(), gen_random_int(), gen_istream(s.read("level_number"))) {
    // ...
}

但我现在有几个问题:

  • 因为这个类没有零args构造函数,所以我必须在我使用战场的类的初始化列表中初始化它。这很麻烦,因为我需要一个来自某个地方的istream。这就引出了下一个问题。
  • 复杂的构造者“雪球”在某个时候。当我在游戏类中使用战场,并在游戏的初始化列表中初始化它时,游戏的构造函数也会变得相当复杂,游戏本身的初始化也会变得很麻烦。(当我决定以istream作为游戏构造函数的参数时)
  • 我需要辅助函数来填充复杂的参数。

我看到了解决这个问题的两种方法:

  • 要么我为没有初始化对象的战场创建一个简单的构造函数。但是这种方法有一个问题,就是我有一个半初始化的对象,也就是一个违反RAII-成语的对象。在对这样一个对象调用方法时,可能会发生奇怪的事情。 游戏:游戏(const设置&s) { random_gen r;int x= r.random_int();int y= r.random_int();ifstream in(s.read("level_number"));in.open();in.open();s.read(“w”),s.read("h"),x,y,in;// .}
  • 或者我在游戏构造函数堆上分配战场。但是我必须注意构造函数中的异常,我必须注意析构函数删除战场。 游戏:游戏(const设置&s) { random_gen r;int x= r.random_int();int y= r.random_int();ifstream in(s.read("level_number"));in.open();this->战场=新战场(s.read(“w”),s.read("h"),x,y,in);// .}

我希望你能看到我正在考虑的问题。我遇到的一些问题是:

  • 对于这种情况,我不知道有什么设计模式吗?
  • 在大型C++项目中,最佳实践是什么?堆上分配了哪些对象,堆栈上分配了哪些对象?为什么?
  • 关于构造函数的复杂性,一般的建议是什么?对构造函数来说,从文件中读取太多了吗?(因为这个问题主要来自于复杂的构造函数。)
EN

Stack Overflow用户

发布于 2012-06-23 12:36:16

但是这种方法有一个问题,就是我有一个半初始化的对象,也就是一个违反RAII-成语的对象。

那不是莱伊。概念是使用对象来管理资源。当您获得堆内存、信号量、文件句柄等资源时,必须将所有权传递给资源管理类。这就是C++中智能指针的意义所在。如果希望拥有对象的唯一所有权,则必须使用unique_ptr;如果希望拥有多个指针,则必须使用shared_ptr

或者我在游戏构造函数堆上分配战场。但是我必须注意构造函数中的异常,我必须注意析构函数删除战场。

如果构造函数抛出异常,则不会调用对象的析构函数,您可能会以半熟对象结束。在这种情况下,您必须记住在抛出异常之前在构造函数中做了哪些分配,并释放所有这些。同样,智能指针将有助于资源的自动清理。参见此常见问题

堆上分配了哪些对象,堆栈上分配了哪些对象?为什么?

尽可能地在堆栈中分配对象。然后,您的对象只有在该块的范围内才有生命。如果有这样的情况无法进行堆分配-例如:您只知道运行时的大小,对象的大小太大,不能放在堆栈上。

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11169366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档