如何解决在构造函数或 init 函数中分配内存?
class MyClass
{
public:
MyClass (int s)
{
if (s <= 0) _size = 1;
else _size = s;
data = new int[_size]; // may throw exception
}
private:
int *data;
int _size;
};
据我所知,在构造函数中抛出异常是不安全的,所以我把 malloc 放到了一个 init 函数中。
class MyClass
{
public:
MyClass (int s)
{
if (s <= 0) _size = 1;
else _size = s;
}
void init()
{
data = new int[_size];
}
private:
int *data;
int _size;
};
我的问题:
解决方法
据我所知,在构造函数中抛出异常是不安全的,所以我把 malloc 放到了一个 init 函数中。
不,这不是“不安全”。这是使构造函数失败的方法。您可能正在考虑析构函数中止或其他有关异常安全保证的问题。
“Init”函数为构造函数引入了两阶段方法,这增加了复杂性。除非您需要在没有例外的环境中工作,否则请避免使用它们。在这种情况下,工厂函数是另一种处理方式。
在构造函数或init函数中分配内存,哪个更好
构造函数。请参阅std::vector
。
如果我选择了init函数,如何保证init函数在调用其他成员函数之前已经调用过?
静态地,如果没有运行时检查或外部工具,您就无法做到。
您可以在 init 函数上设置一个标志,然后检入每个成员函数。
,如果我选择了init函数,如何保证init函数在调用其他成员函数之前已经调用过?
你不能,这是一个大问题!您在这里偶然发现了一个名为 Resource Acquisition is Initialisation (RAII) 的概念。这大致就是您在第 1 部分中编写的内容。如果添加析构函数:
~MyClass() {
delete[] data;
}
然后,您已经开始着手开发最有用的 C++ 容器之一,std::vector
。这与您在这里尝试实现的目标类似。
甚至还有一个 cpp 核心指南:A constructor should create a fully initialised object。
据我所知,在构造函数中抛出异常是不安全的
实际上这是不真实的。事实上,下一个核心准则是If a constructor cannot construct a valid object,throw an exception。
TLDR:使用选项一,在这种情况下 init 不好。
,构造函数的要点是您可以确保在任何其他成员函数之前调用构造函数。
Init 函数来自 c,不被认为是最佳实践
,除了上面的有效答案之外,您还可以考虑使用现有的标准库类来“封装”内存的分配和解除分配:std::unique_ptr<int>
。使用它可以省去您实现一堆方法的需要(例如复制构造函数、移动构造函数、赋值运算符和析构函数;参见 rule of five)。
此外,std::size_t
更适合存储分配的内存量。
最后,以 _
开头的名称通常是保留的,我们避免使用它们。
所以:
#include <memory>
// ...
class MyClass {
public:
using size_type = std::size_t;
using value_type = int;
MyClass (size_type size) :
size_(std::max<size_type>(size,1)),data_(std::make_unique<value_type[]>(size_))
{ }
// etc. etc. - but no need for copy ctor,move ctor,assignments and dtor
private:
std::unique_ptr<value_type[]> data_;
size_type size_;
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。