2016-07-01 35 views
0

Ich habe einen Vektor std::vector<MyClass> myclass_vec(10) mit 10 initialisierten Objekten von MyClass. Jetzt möchte ich diesen Vektor überschleifen und einen Verweis auf jedes MyClass Objekt in einem anderen Vektor speichern std::vector<MyClass> myclass_vec_refs. Der Grund, warum ich Referenzen speichern möchte, ist so, weil ich die Objekte nicht kopieren muss und natürlich auf das gleiche Objekt wie in myclass_vec verweisen muss.Wie speichert man Referenzen auf Objekte aus einem Vektor in einem anderen Vektor in C++?

Aus irgendeinem Grund funktioniert dies nicht wie erwartet. Muss ich std::vector<&MyClass> myclass_vec_refs so deklarieren?

Als ich durch andere Fragen hier gefragt wurde, lese ich über std::unique_ptr. Wenn ich std::vector<std::unique_ptr<MyClass>> myclass_vec(10) ändere, könnte ich keinen Bezug oder Zeiger in myclass_vec_refs haben, da sie eindeutig erklärt werden. Korrigiere mich bitte, wenn ich mich irre.

Ein anderer Ansatz war std::shared_ptr. Da es einen Referenzzähler enthält, könnte ich myclass_vec_refs Punkt auf Objekte in myclass_vec haben, aber ich lese das führt ziemlich viel Overhead und share_ptr sollte nur als letztes Mittel verwendet werden.

Ich weiß auch nicht, ob Referenzieren wie ich versuche, funktioniert. Was passiert, wenn ein Objekt in myclass_vec gelöscht wird? Wird der Vektor myclass_vec_refs um -1 skaliert, weil das Objekt nicht mehr existiert oder nur auf schlechten Speicher zeigt?

Ist es möglich, emplace_back eine Referenz in der myclass_vec_refs Vektor? Da dies das Objekt an Ort und Stelle erzeugt, schätze ich, dass dies nicht funktioniert und nur push_back verwendet werden kann?

+0

Warum nicht einfach speichern einen Iterator in dem anderen Vektor zu verwenden? – NathanOliver

+3

Warum nicht Zeiger anstelle des zugewiesenen Objekts speichern? –

+3

Warum nicht stattdessen Indizes speichern? –

Antwort

1

Sie kann nicht einen Vektor von Referenzen machen. Warum?

Ein Verweis muss immer auf ein tatsächliches Objekt verweisen, und Vektoren nach Entwurf müssen in der Lage sein, "leere" Objekte (d. H. Standardkonstruktor) dynamisch für Sie zu erstellen.

Sie können jedoch einen Vektor von Zeigern erstellen.

Wenn der andere Vektor in irgendeiner Weise geändert wird, werden Ihre Zeiger ungültig. Wenn dies ein Problem für Sie ist, verwenden Sie stattdessen eine Karte oder Set.

+1

Es ist wahr, dass Sie Vektoren von Referenzen nicht haben können, aber Ihre Argumentation ist falsch. Ein Vektor erfordert nicht, dass das Objekt standardmäßig konstruierbar ist. Obwohl einige Elementfunktionen von vector do (mindestens 'resize (size_type count)' und 'vector (size_type count)' sind solche), aber Sie müssen diese Funktionen nicht verwenden, um Vektor zu verwenden. – user2079303

+1

@ user2079303: Eigentlich benötigt 'vector' das nicht. Oder mehr auf den Punkt, "Vektor" * allein * keine Kopie/Umzug Anforderung auferlegt. Es sind die Methoden von 'vector', die tatsächlich Elemente einfügen/entfernen, die diese Anforderung auferlegen. Die grundlegende Sache 'vector ' verlangt von 'T' ist löschbar über die' destroy' Funktion des Zuordners. Und für 'std :: allocator' sind Referenzen nicht. –

+0

@NicolBolas Oh, ich habe den gleichen Fehler gemacht, den ich korrigiert habe. – user2079303

1

Wie beantwortet hier: Strange Template Deduction

Der Trick ist std::reference_wrapper<>

#include <algorithm> 
#include <iostream> 
#include <vector> 

template<typename container_ty_, class Comp> 
auto where(container_ty_& V, Comp&& comp) 
{ 
    using value_type = typename container_ty_::value_type; 
    using reference = 
    std::conditional_t< 
     std::is_const<container_ty_>::value, 
     std::reference_wrapper<const value_type>, 
     std::reference_wrapper<value_type> 
    >; 

    std::vector<reference> cursor; 

    for(auto& VAL : V) 
     if(comp(VAL)) 
      cursor.push_back(VAL); 

    return cursor; 
} 

int main(int argc, char** argv) { 
    std::vector<int> tVect = {0, 5, 2, 1, 7, 9}; 

    //Why must std::vector<int> be passed... 
    auto vec = where(tVect, [](const int& V) -> bool { return V > 5; }); 

    std::for_each(vec.begin(), vec.end(), [] (int& v) { std::cout << v++ << std::endl; }); 
    std::cout << std::endl; 
    std::for_each(tVect.begin(), tVect.end(), [](const int& v) { std::cout << v << std::endl; }); 
} 
+0

@Sean M .: Dies ist die wahre Antwort auf alle Ihre Fragen! – Roland