list学习记录
数据结构
从上面的图示可以看出list实际上是一个双向的循环链表,list里面有一个__list_node类型的指针,__list_node又有三根指针。分别是begin,end,和data熟悉双向循环链表的应该很清楚各自的作用了,这里就不多讲了。就是后面有一个灰色的node,是双向循环链表的最后一个元素的下一个元素。
上面是迭代器的操作,迭代器实际是一个对象但是能够模拟指针的行为,*号操作符重载实际上是去取了node的数据域,->又去调用了星号操作符重载函数,返回数据域的指针还有前加加和后加加就是让迭代器去移动到链表的下一位。为了测试list是否是一个循环链表,下面写了一个测试:
#include <list>
#include <iostream>
using namespace std;
class Test
{
public:
Test(string s)
{
str = s;
cout<<"Test creat\n";
}
~Test()
{
cout<<"Test delete:"<<str<<endl;
}
Test& operator=(const Test& test)
{
cout << "调用例赋值构造函数" << endl;
this->str = test.str;
return *this;
}
Test& CopyTest(const Test& test)
{
cout << "调用例拷贝构造函数" << endl;
this->str = test.str;
return *this;
}
string& getStr()
{
return str;
}
void setStr(string s)
{
str = s;
}
void print()
{
cout<<str<<endl;
}
private:
string str;
};
int main()
{
list<Test> lst;
Test test1("11");
Test test2("22");
Test test3("33");
lst.push_back(test1);
lst.push_back(test2);
lst.push_back(test3);
list<Test>::iterator it = lst.end();
it++;
test1.print();
(*it).print();
}
从上面的结果是可以看出list是一个双向的循环链表的的,并且还将test1里面的内容重新拷贝了一份到list里面这样test1和list容器里面的内容就相互独立不会影响了。
#include <list>
#include <iostream>
using namespace std;
class Test
{
public:
Test(string s)
{
str = s;
cout<<"Test creat\n";
}
~Test()
{
cout<<"Test delete:"<<str<<endl;
}
Test& operator=(const Test& test)
{
cout << "调用例赋值构造函数" << endl;
this->str = test.str;
return *this;
}
Test(const Test& test)
{
cout << "调用例拷贝构造函数" << endl;
this->str = test.str;
}
string& getStr()
{
return str;
}
void setStr(string s)
{
str = s;
}
void print()
{
cout<<str<<endl;
}
private:
string str;
};
int main()
{
list<Test> lst;
Test test1("11");
lst.push_back(test1);
list<Test>::iterator it = lst.begin();
it->print();
cout << &(*it) << endl;
cout << &test1 << endl;
lst.erase(it);
cout << &(*it) << endl;
it->print();
}
这段代码就比较神奇了,我明明已经将test所指向的空间释放了,也确实调用了析构函数,但还是执行了print函数,我只能猜想这里虽然释放了空间但是没有将it指向nullptr,所以只要原来空间的内容还没擦除,应该还是可以访问的,但是这个迭代器已经失效了。为什么?
#include <list>
#include <iostream>
using namespace std;
class Test
{
public:
Test(string s)
{
str = s;
cout<<"Test creat\n";
}
~Test()
{
cout<<"Test delete:"<<str<<endl;
}
Test& operator=(const Test& test)
{
cout << "调用例赋值构造函数" << endl;
this->str = test.str;
return *this;
}
Test(const Test& test)
{
cout << "调用例拷贝构造函数" << endl;
this->str = test.str;
}
string& getStr()
{
return str;
}
void setStr(string s)
{
str = s;
}
void print()
{
cout<<str<<endl;
}
private:
string str;
};
int main()
{
list<Test> lst;
Test test1("11");
Test test2("22");
lst.push_back(test1);
lst.push_back(test2);
list<Test>::iterator it = lst.begin();
it->print();
cout << &(*it) << endl;
cout << &test1 << endl;
lst.erase(it);
cout << &(*it) << endl;
it->print();
it++;
it->print();
}
如果没失效就还能访问到下一个元素,但这里却报段错误,说明这个迭代器已经失效了,但是erase()会返回下一个好的迭代器:
#include <list>
#include <iostream>
using namespace std;
class Test
{
public:
Test(string s)
{
str = s;
cout<<"Test creat\n";
}
~Test()
{
cout<<"Test delete:"<<str<<endl;
}
Test& operator=(const Test& test)
{
cout << "调用例赋值构造函数" << endl;
this->str = test.str;
return *this;
}
Test(const Test& test)
{
cout << "调用例拷贝构造函数" << endl;
this->str = test.str;
}
string& getStr()
{
return str;
}
void setStr(string s)
{
str = s;
}
void print()
{
cout<<str<<endl;
}
private:
string str;
};
int main()
{
list<Test> lst;
Test test1("11");
Test test2("22");
Test test3("33");
Test test4("44");
lst.push_back(test1);
lst.push_back(test2);
lst.push_back(test3);
lst.push_back(test4);
list<Test>::iterator it = lst.begin();
it++;
it = lst.erase(it);
it->print();
it++;
it->print();
it--;
it--;
it->print();
}
如有错误希望指正。