我只是C ++的新手,我正在尝试为我的工作制作一些我的第一堂课。但是,在考虑类的结构时,我怀疑并且使用免费存储内存在模板类和内部参数实例之间有点混淆。
让我们考虑一个简单的例子如下。
1 - 模板类
template < unsigned int n, typename T>
class myclass
{
private:
T _data[n];
public:
myclass()
{
for (int i=0;i<n;i++) _data[i] = 0;
}
~myclass(){}
}
2 - 堆内存使用
template < typename T>
class myclass
{
private:
unsigned int _n;
T *_data;
public:
myclass(const unsigned int &m)
{
_n = m;
_data = new T[_n];
for (int i=0;i<n;i++) _data[i] =0.;
}
~myclass(){ delete [] _data;}
}
在上述两种方法之间,哪一个更好?这两者的优点和缺点是什么?有人可以帮我回答这些问题吗?非常感谢你。
答案 0 :(得分:1)
这两种方法都有效。
代码的第一个版本会稍快一些,因为它不包含内部分配。其他好处 - 它内部没有任何故障点。 Con:当您将它用作堆栈上分配的局部变量时,您可能会遇到堆栈溢出情况。
这里的情况略有争议:一方面,在堆栈上分配大缓冲区没有任何问题,同时应谨慎使用。对于拥有大量用户的库,我不建议使用第一种方法,这些用户不知道库中例程中可能分配的内容。
答案 1 :(得分:1)
如果您不需要堆分配,请不要使用它。它比堆栈分配慢,并且需要跟踪分配的对象。
但是你的两个例子真的不具有可比性(就像比较std::array<>
和std::vector<>
):
一个操作堆栈分配数组(如果这足够,坚持下去),ala std::array<>
,要求用户在编译时指定大小。
第二个是操作指向堆分配数组(ala std::vector<>
)的指针,允许您通过重新分配缓冲区来进一步更改大小。 如果您需要运行时调整大小,那么您应该选择此解决方案。
答案 2 :(得分:0)
第一个将:
初始化两次,这可能不是你所期望的!
T _data[n]; // type must be default constructible, init first time here
for (int i=0;i<n;i++) _data[i] = 0; // second init! type must be assignable with int
第二个例子也会初始化2次:
_data = new T[_n]; // default constructor of T
for (int i=0;i<n;i++) _data[i] =0.; // again assigning a value which is second init
你写的是std :: array或std :: vector的坏版本。根本不做: - )
你没有考虑过:
如果您的算法中的任何操作都会引发异常,该怎么办?如果在禁用异常的环境中编译,可能new
无法分配内存并抛出或返回nullptr,可能默认构造函数或赋值将抛出。