Jest bardziej subtelny, niż sugerują inne odpowiedzi. Nie ma absolutnego podziału między danymi na stosie a danymi na stercie w zależności od tego, jak je zadeklarujesz. Na przykład:
std::vector<int> v(10);
W treści funkcji, która deklaruje vector
(dynamiczną tablicę) dziesięciu liczb całkowitych na stosie. Ale magazyn zarządzany przez the vector
nie znajduje się na stosie.
Ach, ale (inne odpowiedzi sugerują) czas życia tego magazynu jest ograniczony przez czas życia vector
samego siebie, który tutaj jest oparty na stosie, więc nie ma znaczenia, jak jest zaimplementowany - możemy traktować go tylko jako obiekt oparty na stosie z semantyką wartości.
Skąd. Załóżmy, że funkcja była:
void GetSomeNumbers(std::vector<int> &result)
{
std::vector<int> v(10);
// fill v with numbers
result.swap(v);
}
Tak więc wszystko, co ma swap
funkcję (i każdy złożony typ wartości powinien ją mieć) może służyć jako rodzaj możliwego do ponownego powiązania odniesienia do niektórych danych sterty w systemie, który gwarantuje jednego właściciela tych danych.
Dlatego nowoczesne podejście C ++ polega na tym, aby nigdy nie przechowywać adresu danych sterty w nagich lokalnych zmiennych wskaźnikowych. Wszystkie alokacje sterty muszą być ukryte w klasach.
Jeśli to zrobisz, możesz myśleć o wszystkich zmiennych w swoim programie tak, jakby były prostymi typami wartości i całkowicie zapomnieć o sterty (z wyjątkiem pisania nowej klasy opakowującej podobnej do wartości dla niektórych danych sterty, co powinno być niezwykłe) .
Musisz tylko zachować jedną specjalną wiedzę, która pomoże Ci zoptymalizować: tam, gdzie to możliwe, zamiast przypisywać jedną zmienną do drugiej w następujący sposób:
a = b;
zamień je w ten sposób:
a.swap(b);
ponieważ jest znacznie szybszy i nie generuje wyjątków. Jedynym wymaganiem jest to, że nie musisz b
nadal utrzymywać tej samej wartości ( a
zamiast tego otrzyma wartość, która zostałaby skasowana a = b
).
Wadą jest to, że takie podejście wymusza zwracanie wartości z funkcji za pośrednictwem parametrów wyjściowych zamiast rzeczywistej wartości zwracanej. Ale naprawiają to w C ++ 0x za pomocą odwołań do rvalue .
W najbardziej skomplikowanych sytuacjach możesz doprowadzić ten pomysł do skrajności i użyć inteligentnej klasy wskaźnika, takiej jak ta, shared_ptr
która jest już w tr1. (Chociaż argumentowałbym, że jeśli wydaje ci się, że tego potrzebujesz, prawdopodobnie wyszedłeś poza słodkie miejsce zastosowania Standard C ++).