Підхід , який ви описуєте сумісний не тільки з C ++, але і з його ( в основному) мови підмножина C . Навчитися розробляти пов'язаний список у стилі С - це хороший спосіб познайомитись із методами програмування низького рівня (наприклад, ручним управлінням пам'яттю), але це, як правило, не найкраща практика для сучасної розробки C ++.
Нижче я реалізував чотири варіанти, як керувати списком елементів у C ++.
raw_pointer_demo
використовує той же підхід, що і ваш - ручне управління пам’яттю, необхідне з використанням необроблених покажчиків. Використання C ++ тут стосується лише синтаксичного цукру , а застосовуваний підхід інакше сумісний з мовою С.
- У
shared_pointer_demo
списку управління все ще виконується вручну, але управління пам'яттю є автоматичним (не використовує необроблені покажчики). Це дуже схоже на те, що ви, напевно, відчували з Java.
std_list_demo
використовує list
контейнер стандартної бібліотеки . Це показує, як набагато простіше, якщо ви покладаєтесь на існуючі бібліотеки, а не на власній власній бібліотеці.
std_vector_demo
використовує vector
контейнер стандартної бібліотеки . Це управляє сховищем списку в одному суміжному виділенні пам'яті. Іншими словами, немає покажчиків на окремі елементи. У деяких досить екстремальних випадках це може стати значно неефективним. Однак для типових випадків це рекомендована найкраща практика управління списками на C ++ .
Зауважимо: з усього цього лише raw_pointer_demo
фактично потрібно, щоб список було явно знищено, щоб уникнути "протікання" пам'яті. Інші три методи автоматично знищують список та його вміст, коли контейнер виходить із сфери застосування (після завершення функції). Сенс у тому, що C ++ може бути дуже «подібним до Java» у цьому плані - але лише якщо ви вирішите розробити свою програму, використовуючи інструменти високого рівня, що є у вашому розпорядженні.
/*BINFMTCXX: -Wall -Werror -std=c++11
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <list>
#include <vector>
#include <memory>
using std::cerr;
/** Brief Create a list, show it, then destroy it */
void raw_pointer_demo()
{
cerr << "\n" << "raw_pointer_demo()..." << "\n";
struct Node
{
Node(int data, Node *next) : data(data), next(next) {}
int data;
Node *next;
};
Node * items = 0;
items = new Node(1,items);
items = new Node(7,items);
items = new Node(3,items);
items = new Node(9,items);
for (Node *i = items; i != 0; i = i->next)
cerr << (i==items?"":", ") << i->data;
cerr << "\n";
// Erase the entire list
while (items) {
Node *temp = items;
items = items->next;
delete temp;
}
}
raw_pointer_demo()...
9, 3, 7, 1
/** Brief Create a list, show it, then destroy it */
void shared_pointer_demo()
{
cerr << "\n" << "shared_pointer_demo()..." << "\n";
struct Node; // Forward declaration of 'Node' required for typedef
typedef std::shared_ptr<Node> Node_reference;
struct Node
{
Node(int data, std::shared_ptr<Node> next ) : data(data), next(next) {}
int data;
Node_reference next;
};
Node_reference items = 0;
items.reset( new Node(1,items) );
items.reset( new Node(7,items) );
items.reset( new Node(3,items) );
items.reset( new Node(9,items) );
for (Node_reference i = items; i != 0; i = i->next)
cerr << (i==items?"":", ") << i->data;
cerr<<"\n";
// Erase the entire list
while (items)
items = items->next;
}
shared_pointer_demo()...
9, 3, 7, 1
/** Brief Show the contents of a standard container */
template< typename C >
void show(std::string const & msg, C const & container)
{
cerr << msg;
bool first = true;
for ( int i : container )
cerr << (first?" ":", ") << i, first = false;
cerr<<"\n";
}
/** Brief Create a list, manipulate it, then destroy it */
void std_list_demo()
{
cerr << "\n" << "std_list_demo()..." << "\n";
// Initial list of integers
std::list<int> items = { 9, 3, 7, 1 };
show( "A: ", items );
// Insert '8' before '3'
items.insert(std::find( items.begin(), items.end(), 3), 8);
show("B: ", items);
// Sort the list
items.sort();
show( "C: ", items);
// Erase '7'
items.erase(std::find(items.begin(), items.end(), 7));
show("D: ", items);
// Erase the entire list
items.clear();
show("E: ", items);
}
std_list_demo()...
A: 9, 3, 7, 1
B: 9, 8, 3, 7, 1
C: 1, 3, 7, 8, 9
D: 1, 3, 8, 9
E:
/** brief Create a list, manipulate it, then destroy it */
void std_vector_demo()
{
cerr << "\n" << "std_vector_demo()..." << "\n";
// Initial list of integers
std::vector<int> items = { 9, 3, 7, 1 };
show( "A: ", items );
// Insert '8' before '3'
items.insert(std::find(items.begin(), items.end(), 3), 8);
show( "B: ", items );
// Sort the list
sort(items.begin(), items.end());
show("C: ", items);
// Erase '7'
items.erase( std::find( items.begin(), items.end(), 7 ) );
show("D: ", items);
// Erase the entire list
items.clear();
show("E: ", items);
}
std_vector_demo()...
A: 9, 3, 7, 1
B: 9, 8, 3, 7, 1
C: 1, 3, 7, 8, 9
D: 1, 3, 8, 9
E:
int main()
{
raw_pointer_demo();
shared_pointer_demo();
std_list_demo();
std_vector_demo();
}