Push _back用于您自己的STL容器c++
Push _back for your own STL container C++
我想编写一个用于包含元素序列的类模板。我正在研究一种方法,它的行为就像矢量中的push_back()。这是我目前所做的:
template <class T, int N>
class mysequence{
T memblock[N];
public:
void setmember(T value);
T getmember(int x);
};
template <class T, int N>
void mysequence<T, N>::setmember(T value) {
if (sizeof(memblock) == 1) memblock[0] = value;
else {
int y = sizeof(memblock) / sizeof(memblock[0]);
memblock[y] = value;
}
}
template <class T, int N>
T mysequence<T, N>::getmember(int x) {
return memblock[x];
}
int main()
{
mysequence < int, 14 > myints;
myints.setmember(9);
cout << myints.getmember(0);
}
返回:
-858993460
显示错误信息。据我所知,一个空类或结构的大小是1。但我也试过:
if (sizeof(memblock) == NULL) memblock[0] = value;
但还是一样。我不知道我的代码出了什么问题。如果大家有什么意见,我将不胜感激。
问题在于你使用了sizeof。它不会告诉你有多少元素,而只告诉你使用了多少内存(N * sizeof(T))。为了跟踪所包含的元素,您可以设置一个单独的计数器。
您要求getmember()
返回数组的第一个元素,但setmember()
从未填充该元素,除非 T
为char
, unsigned char
或bool
,并且N
为1。在任何其他组合中,setmember()
存储数组末尾以外的值。如果您想在最后一个元素中存储一个值,则使用N-1代替(不需要计算y
,因为它将匹配N
):
template <class T, int N>
void mysequence<T, N>::setmember(T value) {
memblock[N-1] = value;
}
但是,这在多元素数组中是没有用的。由于您想模仿push_back()
,您需要让setmember()
将值存储在最后可用的元素中,而不是:
template <class T, int N>
class mysequence{
T memblock[N];
int count;
public:
mysequence() : count(0) {}
void setmember(T value);
T getmember(int x);
};
template <class T, int N>
void mysequence<T, N>::setmember(T value) {
if (count < N) {
memblock[count-1] = value;
++count;
}
else
throw length_error("sequence is full");
}
template <class T, int N>
T mysequence<T, N>::getmember(int x) {
if ((x < 0) || (x >= count))
throw out_of_range("x is out of range");
return memblock[x];
}
int main()
{
mysequence < int, 14 > myints;
myints.setmember(9);
cout << myints.getmember(0);
}
或者,你可以简单地摆脱你的数组,使用一个真正的向量来代替:
template <class T>
class mysequence{
vector<T> memblock;
public:
void setmember(T value);
T getmember(int x);
};
template <class T>
void mysequence<T>::setmember(T value) {
memblock.push_back(value);
}
template <class T>
T mysequence<T>::getmember(int x) {
return memblock[x];
}
int main()
{
mysequence < int > myints;
myints.setmember(9);
cout << myints.getmember(0);
}
这应该表明问题:
template <class T, int N>
void mysequence<T, N>::setmember(T value) {
if (sizeof(memblock) == 1) memblock[0] = value;
else {
int y = sizeof(memblock) / sizeof(memblock[0]);
cout << "y: " << y << endl;
memblock[y] = value;
}
}
当使用:
调用时myints.setmember(1);
myints.setmember(5);
myints.setmember(8);
我得到了输出:
y: 14
y: 14
y: 14
y
总是相同的,因为它是通过查找底层存储数组的长度来计算的,而不是实际存储在该数组中的元素数量。
如果没有正确填充数组的元素,调用getmember
时得到的值将取出数组中未初始化的元素。这就是你获得垃圾值的地方,比如-858993460
(注意,在我的机器上,我在这里得到了一个不同的值,这与我们在这里的UB一致)。
如果你想支持一个push_back
类型的方法,不需要一个索引传递值,那么你需要改变你的设计,有一个字段来跟踪到目前为止你已经插入到数组中的元素的数量。
另外,我会做一些检查,看看是否有足够的空间来实际把最新的元素放到数组的后面。
您误解了push_back的功能。push_back所做的是将元素添加到数组的末尾,即使是空数组。所以我修改了你的函数的一些功能,并在注释中注明。
#include <iostream>
#include <algorithm>
using namespace std;
template <class T, int N>
class mysequence{
T *memblock;//You will need a pointer for enabling the resizing of the array
int size;//This is used to keep track of the size of the array
public:
mysequence();
mysequence(const mysequence &src);
~mysequence();
void setmember(T value);
T getmember(int x);
void push_back(T value);
mysequence& operator=(const mysequence &src);
};
template <class T, int N>
void mysequence<T, N>::mysequence(){
size = N;
memblock = new T[N];
}
template <class T, int N>
void mysequence<T, N>::mysequence(const mysequence<T,N> &src){
size = src.size
memblock = new T[size];
copy(src.memblock, src.memblock+size, memblock);
}
template <class T, int N>
void mysequence<T, N>::~mysequence(){
delete[] memblock;
}
template <class T, int N>
void mysequence<T, N>::setmember(T value) {//this setmember function just sets the last element of the array to the value specified
if( size > 0 ){
memblock[size-1] = value;
}
}
template<class T, int N>
void mysequence<T,N>::push_back(T value){
T *pointer = new T[size+1];
copy(memblock, memblock+size, pointer);
pointer[size] = value;
delete[] arr;
arr = pointer;
size++;
}
template <class T, int N>
T mysequence<T, N>::getmember(int x) {
return memblock[x];
}
template<class T, int N>
mysequence<T,N>& mysequence<T,N>::operator=(const mysequence<T,N> &src){
T *pointer = new T[src.size];
copy(src.memblock, src.memblock+src.size, pointer);
delete[] arr;
arr = pointer;
size = src.size;
}
int main()
{
mysequence < int, 14 > myints;
myints.setmember(9);
cout << myints.getmember(13)<<endl;//the indexing is one less. so to access the last element, you need to specify 13. As other values are not initialized, they will have garbage value in them
myints.push_back(1);
cout<<myints.getmember(14)<<endl;
return 0;
}
- 在STL容器中使用模板类
- 检查函数返回类型是否与STL容器类型值相同
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 对象 C++ 向量的 STL 容器
- 如何在不破坏现有应用程序的情况下更改 API 中 stl 容器的数据类型?
- 在 STL 容器的 STL 容器上调用 clear
- "迭代器"和"const_iterator"不是 STL 容器的必需成员?
- 删除包含包含动态对象的 STL 容器的智能指针
- C++:在子类中扩展静态 STL 容器/映射成员?
- ostream 运算符<< 为获取 STL 容器而过载,传递 std::string 会破坏它?
- 没有 STL 容器的迭代器
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 接受任何 STL 容器的函数
- C++ STL 容器中优先级搜索的优雅方法
- 我们如何打印出C++ STL 容器的value_type?
- 获取嵌套 stl 容器的大小(以字节为单位)
- 如何在C++中重新实现包含指针的 STL 容器的类的迭代器
- 迭代器和 STL 容器的关系
- 如何用索引增量generate_n填充STL容器