【发布时间】:2021-09-16 01:59:24
【问题描述】:
我试图定义自己的类模板Array<T> 来练习模板的使用。
我生成的代码可以正确构建,但是执行时会出现以下错误
terminate called after throwing an instance of 'std::bad_array_new_length'
what(): std::bad_array_new_length
我想我已经找到了解决问题的方法,但我很想看看之前的代码中是否存在潜在错误,如果有,是哪一个。
这是我之前写的代码:
#include <iostream>
class Empty{
private:
char error;
public:
Empty(char e) : error(e) { std::cout << "Azione non disponibile, lista vuota" << std::endl;}
};
template <class T>
class Array;
template <class T>
std::ostream& operator<<(std::ostream&,const Array<T>&);
template <class T>
class Array{
friend std::ostream& operator<< <T> (std::ostream&,const Array<T>&);
private:
T* arr;
unsigned int size;
unsigned int capacity;
static T* copia(T* a, unsigned int s, unsigned int c){
if(c > 0) {
T* app = new T[c];
for (int i = 0; i<s; ++i) {
app[i] = a[i];
}
return app;
}else return nullptr;
}
public:
Array(int k = 0, const T& t = T()) : size(k > 0 ? k : 0), capacity(size), arr(k > 0 ? new T[size] : nullptr){
for (int i = 0; i < k ; ++i) arr[i] = t;
}
Array(const Array& a) : size(a.size), capacity(a.capacity), arr(copia(a.arr,a.size,a.capacity)){}
Array& operator=(const Array& a){
if(this != &a){
delete[] arr;
capacity = size = a.size;
arr = copia(a.arr,a.size,a.capacity);
}
return *this;
}
~Array(){delete[] arr;}
void pushBack(const T& t) {
if(size == capacity){
capacity > 0 ? capacity *= 2 : capacity = 1;
T* app = copia(arr,size, capacity);
delete[] arr;
arr = app;
}
++size;
arr[size-1] = t;
}
T popBack() {
if (size != 0) {
T temp = arr[size - 1];
--size;
return temp;
} else throw Empty('e');
}
};
template <class T>
std::ostream& operator<<(std::ostream& os ,const Array<T>& a){
for (int i = 0; i < a.size; ++i) {
os << a.arr[i] << ' ';
}
std::cout << std::endl;
return os;
}
int main(){
Array<int> a(5,5),e;
std::cout << a << std::endl;
a.pushBack(16);
a.pushBack(17);
a.pushBack(18);
std::cout << a << std::endl;
return 0;
}
如果我在没有 a.pushBack(x) 函数调用的情况下运行此代码,它可以工作。
只要我插入一个函数调用,我就会在输出中得到那个错误。
在调试时,我意识到我写T* arr 的那行不是正确的。
知道构造函数按照自己子对象的初始化顺序,第一个要构造的元素就是指针。
由于我正在尝试创建维度为size 的T 元素向量,因此正确地给了我错误,因为我尚未初始化整数大小。
所以我通过换行来解决它。
template <class T>
class Array{
friend std::ostream& operator<< <T> (std::ostream&,const Array<T>&);
private:
unsigned int size;
unsigned int capacity;
T* arr;
...
};
但此时我想知道:为什么,如果我不进行函数调用,知道构造时的大小是未定义的,我不会得到同样的错误?
从逻辑上讲,在这种情况下也应该出现问题,但是似乎一切正常:
PS:不要指望我没有处理抛出的异常,代码还没有完全完成,但目前我渴望至少实现三法则。
【问题讨论】:
-
“似乎有效”是未定义行为的一种非常常见的表现形式。您不能将逻辑应用于未定义的事物。
-
@molbdnilo 是的,你完全正确。由于我今年才开始用 c++ 编程,您对某种质量的编译器和调试器有什么建议吗?因为我基本上用的是MinGW。
-
迂腐模式:“类模板”,而不是“模板类”。
-
@Evg 哎呀,我的错。我没注意到!谢谢
-
@LukeTheWolf“模板类”和“模板函数”被广泛使用,但是,正如Walter Brown says,单词顺序很重要:“牛奶巧克力”和“巧克力牛奶”非常不同。类模板和函数模板。
标签: c++ arrays c++11 templates