五法则
逐步查看 C++ 链表的析构、拷贝和移动。
所有内容均在此浏览器中模拟,不会发送到任何服务器。
操作
调用构造函数
调用构造函数
l1未构造
∅
- 当前
- 指针
第 1 / 26 步
l1
l2
l3
代码
#include <iostream>
#include <utility>
class Nodo { // 节点保存数据和指向下一个节点的指针
private: // 私有属性:只有方法可以访问
int dato_;
Nodo* siguiente_;
public:
Nodo(int dato, Nodo* siguiente = nullptr) {
dato_ = dato;
siguiente_ = siguiente;
}
int getDato() const { return dato_; }
void setDato(int dato) { dato_ = dato; }
Nodo* getSiguiente() const { return siguiente_; }
void setSiguiente(Nodo* siguiente) { siguiente_ = siguiente; }
};
class Lista {
private:
Nodo* cabeza_; // 链表的第一个节点
int n_; // 节点数量
public:
Lista() { // 默认构造函数:创建一个空链表
cabeza_ = nullptr;
n_ = 0;
}
~Lista() { // 析构函数:释放所有节点
while (cabeza_ != nullptr) {
Nodo* borra = cabeza_;
cabeza_ = borra->getSiguiente();
delete borra;
}
}
Lista(const Lista& origin) { // 拷贝构造函数:进行深拷贝
cabeza_ = nullptr;
n_ = 0;
Nodo* aux = origin.cabeza_;
while (aux != nullptr) {
insertarElemento(aux->getDato());
aux = aux->getSiguiente();
}
invertirLista(); // 在头部插入会反转顺序,所以要再反转回来
}
Lista& operator=(const Lista& origin) { // 拷贝赋值:先释放旧节点,再进行拷贝
if (this != &origin) { // 防止自我赋值
while (cabeza_ != nullptr) { // 释放链表已有的节点
Nodo* borra = cabeza_;
cabeza_ = borra->getSiguiente();
delete borra;
}
n_ = 0;
Nodo* aux = origin.cabeza_;
while (aux != nullptr) {
insertarElemento(aux->getDato());
aux = aux->getSiguiente();
}
invertirLista();
}
return *this;
}
Lista(Lista&& origin) noexcept { // 移动构造函数:夺取源链表的节点
cabeza_ = origin.cabeza_;
n_ = origin.n_;
origin.cabeza_ = nullptr; // 让源链表保持为空
origin.n_ = 0;
}
Lista& operator=(Lista&& origin) noexcept { // 移动赋值:先释放旧节点,再夺取新节点
if (this != &origin) { // 防止自我赋值
while (cabeza_ != nullptr) { // 释放链表已有的节点
Nodo* borra = cabeza_;
cabeza_ = borra->getSiguiente();
delete borra;
}
cabeza_ = origin.cabeza_;
n_ = origin.n_;
origin.cabeza_ = nullptr; // 让源链表保持为空
origin.n_ = 0;
}
return *this;
}
int getTamano() const { return n_; }
Nodo* getCabeza() const { return cabeza_; }
void insertarElemento(int valor) { // 头部插入:O(1)
Nodo* nodo = new Nodo(valor, nullptr);
n_ += 1;
nodo->setSiguiente(cabeza_);
cabeza_ = nodo;
}
void imprimirLista() const { // 打印每个元素
Nodo* siguiente = cabeza_;
for (int i = 0; i < n_; i++) {
std::cout << siguiente->getDato() << " ";
siguiente = siguiente->getSiguiente();
}
std::cout << std::endl;
}
void eliminarNodo(int indice) { // 删除指定位置的节点
if (indice < 0 || indice >= n_) return; // 索引无效:什么也不做
if (indice == 0) {
Nodo* eliminar = cabeza_;
cabeza_ = eliminar->getSiguiente();
delete eliminar;
n_--;
return;
}
Nodo* eliminanodo_anterio = cabeza_;
for (int i = 0; i < indice - 1; i++) {
eliminanodo_anterio = eliminanodo_anterio->getSiguiente();
}
Nodo* eliminanodo = eliminanodo_anterio->getSiguiente();
eliminanodo_anterio->setSiguiente(eliminanodo->getSiguiente());
delete eliminanodo;
n_--;
}
void invertirLista() { // 原地反转链表
Nodo* anterior = nullptr;
Nodo* actual = cabeza_;
Nodo* siguiente = nullptr;
for (int i = 0; i < n_; i++) {
siguiente = actual->getSiguiente();
actual->setSiguiente(anterior);
anterior = actual;
actual = siguiente;
}
cabeza_ = anterior;
}
};
int main() {
Lista l1;
l1.insertarElemento(10);
l1.insertarElemento(20);
l1.insertarElemento(30);
Lista l2;
l2.insertarElemento(100);
l2 = l1; // 拷贝赋值(不使用 swap)
l2.imprimirLista();
Lista l3;
l3 = std::move(l1); // 移动赋值(不使用 swap)
l3.imprimirLista();
return 0;
}