Pointers work exactly the same way in C++ as they do in Pascal. The only difference is in how you allocate and free the things being pointed at.
For instance, you can declare a local variable and point to it, eg:
int i = 12345;
int *p = &i;
// use p as needed...
This would be equivalent to this in Pascal:
var
i: Integer;
p: ^Integer;
begin
i := 12345;
p := @i;
// use p as needed...
end;
Or, you can use new
and delete
to work with variables allocated dynamically, eg:
someType *data = new someType;
// use data as needed ...
delete data;
Which is equivalent to this in Pascal:
type
someType = record
...
end;
var
data: ^someType;
begin
New(data);
// use data as needed ...
Dispose(data);
end;
However, modern C++ code should strive to avoid using new
/delete
directly as much as possible. Use smart pointers instead (std::unique_ptr
and std::shared_ptr
, via std::make_unique()
and std::make_shared()
), which free memory automatically when they go out of scope and get destroyed. This helps make code safer and more self-documenting as to the ownership semantics of pointed-at data. Use raw pointers only where needed to access data without transferring ownership of it, eg:
void doSomething(someType *data)
{
// use data as needed ...
}
{
auto data = std::make_unique<someType>();
doSomething(data.get());
} // <-- data is freed automatically here!
The type of class you describe is more formally known as a node/element of a "linked list", which is commonly implemented using new
/delete
, eg:
#include <iostream>
struct node
{
int data;
node* next = nullptr;
};
node *head = nullptr;
node *tail = nullptr;
void addToList(int data)
{
node **n = (tail) ? &(tail->next) : &head;
*n = new node{data};
tail = *n;
}
void clearList()
{
node *n = head;
while (n) {
node *next = n->next;
delete n;
n = next;
}
head = tail = nullptr;
}
void printList()
{
node *n = head;
if (n)
{
std::cout << n->data;
while ((n = n->next) != nullptr) {
std::cout << ", " << n->data;
}
}
std::cout << std::endl;
}
int main()
{
addToList(12345);
addToList(67890);
printList();
clearList();
return 0;
}
A linked-list is not a good example for using smart pointers, though. Yes, the head
pointer could be a smart pointer, at least. But you would still have to iterate the list destroying the individual nodes, before the unique_ptr
destroys the head
node. And you might be tempted to make the next
pointers be smart pointers too, but doing that would be a bad idea, as recursive destructor calls can blow up the call stack when destroying large linked-lists. Iterative loops are more suitable for destroying linked-lists, and having next
be a smart pointer is not a good fit for that use-case.
But, in any case, C++ has built-in standard classes for double-linked lists (std::list
) and single-linked lists (std::forward_list
), which handle the linking pointers for you, so you can focus more on your class data and less on how the class instances are linked together, eg:
#include <iostream>
#include <list>
std::list<int> l;
void printList()
{
auto iter = l.begin();
if (iter != l.end())
{
std::cout << *iter;
while (++iter != l.end()) {
std::cout << ", " << *iter;
}
}
std::cout << std::endl;
}
int main()
{
l.push_back(12345);
l.push_back(67890);
printList();
return 0;
}