类模板加副本构造器,进入析构器删除出错
本帖最后由 吃肉的考拉 于 2014-4-9 20:29 编辑#include <iostream>
#include <string>
template <class T>//类模板
class Stack
{
public:
Stack(unsigned int size = 10)
{
std::cout << "进入主构造器\n";
this->size = size;
data = new T;
sp = 0;
flag = 1;
std::cout << "离开主构造器\n";
}
Stack( const Stack &rhs)
{
std::cout << "进入副本构造器\n";
flag =0;
*this = rhs; //该=已经被重载
std::cout << "离开副本构造器\n";
}
~Stack()
{
std::cout << "进入析构造器\n";
delete []data;
std::cout << "离开析构造器\n";
}
Stack & operator = (const Stack &rhs)
{
std::cout << "进入赋值语句重载\n";
if(this != &rhs)
{
std::cout << "是否删除的标志位值为: "<< flag << std::endl;
if(flag)
{
std::cout << "执行删除\n";
delete [] data;
}
data = new T;
*data = *rhs.data; //两个指针,指向不同的地址,但里面的内容值是一样的
}
else
{
std::cout << "赋值号两边为同个对象,不做处理!\n";
}
std::cout <<"离开赋值语句重载\n";
return *this;
}
void push(T value)
{
data = value;
}
T pop()
{
return data[--sp];
}
private:
unsigned int size;
unsigned int sp;
int flag ; //是否在重载=操作符时删除原来的ptr
T *data;
};
int main()
{
Stack<int> intStack(100);
intStack.push(1);
intStack.push(2);
intStack.push(3);
Stack<int> intStack1 = intStack;
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
intStack1.push(1);
intStack1.push(2);
intStack1.push(3);
std::cout << intStack1.pop() << std::endl;
std::cout << intStack1.pop() << std::endl;
std::cout << intStack1.pop() << std::endl;
return 0;
}
本帖最后由 Arthkee 于 2014-4-4 11:23 编辑
吃肉的考拉 发表于 2014-4-4 09:33 static/image/common/back.gif
for(int i = 0; i < rhs.sp;i++)
{
push(rhs.data);
您这样写,是不行的,您看语义,r.data是什么意思,是一个<T>型的数组,而Push呢是要把一个<T>型元素Push进去。
即便这样改完Push的时候rhs.data的指针也要更改(push(*(rhs.data+i)); )。
我的直接把栈数据Copy过来,这种对简单类型变量比较适用。
你的那种对类/struct类型变量能更好应对一点,中间多了个拷贝构造,效率能差异点(轮询过程可以封个函数,友好一点)。
是吧?看你具体需求了,希望对您有帮助。{:1_1:}
自问自答吧,因为这个类里不只一个属性,=重载操作符里只对 指针data进行了操作,没有对size,sp等属性进行赋值。 这好像还是错的 ,求解决 这个应该涉及到浅拷贝,具体可以看看C++的相关章节,我大概改了下,你可以看看,构造的时候多了类内变量初始化,以及拷贝的过程。
安全检测没有做,例如Push的时候比较下容量,删除的时候检查sp,拷贝的时候检查SP和size #include <iostream>
#include <string>
template <class T>//类模板
class Stack
{
public:
Stack()
{
m_Size = 0;
m_sp = 0;
m_flag = 1;
m_data = NULL;
}
Stack(unsigned int size)
{
std::cout << "进入主构造器\n";
this->m_Size = size;
m_data = new T;
m_sp = 0;
m_flag = 1;
std::cout << "离开主构造器\n";
}
Stack( const Stack &rhs)
{
std::cout << "进入副本构造器\n";
m_Size = 0;
m_sp = 0;
m_flag = 1;
m_data = NULL;
*this = rhs; //该=已经被重载
std::cout << "离开副本构造器\n";
}
~Stack()
{
std::cout << "进入析构造器\n";
delete []m_data;
std::cout << "离开析构造器\n";
}
Stack & operator = (const Stack &rhs)
{
std::cout << "进入赋值语句重载\n";
if(this != &rhs)
{
std::cout << "是否删除的标志位值为: "<< m_flag << std::endl;
if(m_flag && m_data)
{
std::cout << "执行删除\n";
delete [] m_data;
m_data = NULL;
}
//赋值语句
m_Size = rhs.m_Size;
m_sp = rhs.m_sp;
m_data = new T;
memcpy_s(m_data, m_Size * sizeof(T), rhs.m_data, m_sp * sizeof(T));
//*data = *rhs.data; //两个指针,指向不同的地址,但里面的内容值是一样的
}
else
{
std::cout << "赋值号两边为同个对象,不做处理!\n";
}
std::cout <<"离开赋值语句重载\n";
return *this;
}
void push(T value)
{
m_data = value;
}
T pop()
{
return m_data[--m_sp];
}
private:
unsigned int m_Size;
unsigned int m_sp;
int m_flag ; //是否在重载=操作符时删除原来的ptr
T* m_data;
};
int main()
{
Stack<int> intStack(100);
intStack.push(1);
intStack.push(2);
intStack.push(3);
Stack<int> intStack1 = intStack;
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
intStack1.push(4);
intStack1.push(5);
intStack1.push(6);
std::cout << intStack1.pop() << std::endl;
std::cout << intStack1.pop() << std::endl;
std::cout << intStack1.pop() << std::endl;
return 0;
} Arthkee 发表于 2014-4-4 08:40 static/image/common/back.gif
#include
#include
memcpy_s(m_data, m_Size * sizeof(T), rhs.m_data, m_sp * sizeof(T));
这句编译通不过咧 吃肉的考拉 发表于 2014-4-4 09:12 static/image/common/back.gif
memcpy_s(m_data, m_Size * sizeof(T), rhs.m_data, m_sp * sizeof(T));
这句编译通不过咧
for(int i = 0; i < rhs.sp;i++)
{
push(rhs.data);
}我这么搞了
吃肉的考拉 发表于 2014-4-4 09:12 static/image/common/back.gif
memcpy_s(m_data, m_Size * sizeof(T), rhs.m_data, m_sp * sizeof(T));
这句编译通不过咧
这句是安全函数,可以改为memcpy(m_data, rhs.m_data, m_sp * sizeof(T)); 呵呵!楼上的技术很高以后还要向你多多学习呢!我在调试这个程序的时候,当程序运行到析构造器的时候,程序就发生异常了,反汇编过来的话,发现是程序是调用到这个函数的时候:00401CAC call operator delete (00409390)就发生异常了,最后我也困惑了,经过你的这番讲解之后原来是这样啊!
本帖最后由 Arthkee 于 2014-4-4 14:54 编辑
青玄 发表于 2014-4-4 12:49 static/image/common/back.gif
呵呵!楼上的技术很高以后还要向你多多学习呢!我在调试这个程序的时候,当程序运行到析构造器的时候,程序 ...
delete 崩溃的原因一般就是指针已经被释放掉了,或者赋值错误指针指向了一个不存在的地址(中间不正确的赋值,或者根本没初始化),可以在delete之前看看指针的数据是什么样的,从这两个方面出发,应该就能找到问题了。我记得早上看的时候应该是没初始化。{:1_1:} 本帖最后由 吃肉的考拉 于 2014-4-9 20:37 编辑
Arthkee 发表于 2014-4-3 22:20 http://bbs.fishc.com/static/image/common/back.gif
您这样写,是不行的,您看语义,r.data是什么意思,是一个型的数组,而Push呢是要把一个型元素Push进去。 ...
for(int i = 0; i < rhs.sp; i++)
{
push(rhs.data);
}
你的我也编译过了~
页:
[1]