?
Nexus schrieb:
Ja, boost::ptr_vector räumt selbst auf. Ich persönlich bin aber spätestens seit C++11 kein Fan mehr von den Pointer-Containern, siehe hier.
...wobei ich im Falle von vector<unique_ptr<T>> die extra Indirektion, die man da durchführen muss, schon nervig finde. Das const wird auch leider nicht propagiert:
void foo(vector<unique_ptr<int>> const& vec)
{
if (!vec.empty()) {
*vec.front() += 17; // klappt!
}
}
Wenn Du "unhandliche Objekte" nur deswegen einzeln im Heap anlegst und die Adresse in einem unique_ptr speicherst, damit das Speichern im Vektor "effizienter" wird, ist diese Zeiger-Semantik eigentlich nicht das, was man haben will.
Klar, ich kann mir ausgehend von vector<unique_ptr<T>> immer noch per boost::indirect_iterator zwei Iteratoren bauen, wo ich diese nervige extra Indirektion nicht mehr brauche und worüber auch ein const hinzugefügt werden kann. Das ist schon mal was.
Aber vielleicht wäre da ein anderer Wrapper nicht ganz verkehrt. Ich habe in meiner Sammlung noch eine Kuh (copy-on-write). Hier nur mal eine vereinfachte und ungetestete Skizze davon:
template<class T>
class cow
{
public:
cow()
{
static const auto def = make_shared<T>(); // cached default
ptr = def;
}
cow(T const& x)
: ptr(make_shared<T>(x))
{}
cow(T && x)
: ptr(make_shared<T>(std::move(x)))
{}
template<class U, class...More
,class=typename std::enable_if<
!std::is_convertible<U,cow const&>::value &&
std::is_constructible<T,U,More...>::value
>::type
>
cow(U && x, More && ... xx)
: ptr(make_shared<T>(forward<U>(x),forward<More>(xx))
{}
T const& read() const {return *ptr;}
T const& operator*() const {return *ptr;}
T const* operator->() const {return ptr.get();}
operator T const&() const& {return *ptr;}
operator T const&() const&& = delete; // zu unsicher
T& write()
{
if (!ptr.unique()) {
ptr = make_shared<T>(*ptr);
}
assert(ptr.unique());
return *ptr;
}
private:
shared_ptr<T> ptr;
};
was man dann so nutzen könnte:
vector<cow<unhandlicher_typ>> vec;
vec.emplace_back(dies,und,jenes);
...
for (auto& x : vec) {
x.write().veraendere_dich(1,2,3);
}
for (unhandlicher_typ const& x : vec) {
cout << x.get_something() << endl;
}
Und sonst könnte man ja auch einfach mal std::deque<T> mit emplace ausprobieren ohne unique_ptr und ohne cow . Da sollte auch nicht so viel kopiert werden. Und das wäre mein aktueller Tipp für cl90: Probier mal std::deque und/oder emplace aus.
cl90 schrieb:
ok dann werd ich mal lesen wie das geht mit dem umstieg.
Ich glaube, beim Microsoft Compiler musst du gar nix besonderes machen. Er unterstützt automatisch schon C++11 Features, sofern einigermaßen aktuell. Beim GCC kommt es auf die Version an. Ggf brauchst du den Compilerschalter "-std=c++0x" oder "-std=c++11".