2016-08-03 11 views
0

Ich gebe die folgenden Codes, um meine Frage zu veranschaulichen. Angenommen, LargeClass ist eine Klasse enthält viele interne Variablen wie die folgenden Codes zeigen.Möglichkeiten zum Einbau großer Klassenelemente in C++

class LargClass 
{ 
    public: 
     std::vector<int> abc={1,2,3, ...., 10000}; 

} 

Nehmen wir nun an LargeClass ein Element einer anderen Klasse wird Abc wie die folgenden Codes zeigen:

class Abc 
{ 
public: 
     std::vector<LargeClass> obj; 

}; 

Als std::vector<LargeClass> sehr kostspielig ist initialisiert zu werden, wenn Abc Klassenobjekt aufgebaut ist, ist eine mögliche Lösung ist, Konstrukt std::vector<LargeClass> Element nach Abc wird als die folgenden Codes aufgebaut:

Statt std::vector<LargeClass> in eine teure Art und Weise initialisiert werden:

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp) 
     { 
      obj = objTemp; 
     } 
} 

Natürlich gibt es andere Lösungen. Eine Lösung ist, Zeiger

class Abc 
    { 
public: 
    Abc(std::vector<LargeClass> &obj) 
    { 
     pObj = &obj; 
    } 
std::vector<LargeClass> *pObj; 
} 

Mit dieser Lösung zu verwenden, jedoch müssen wir sicherstellen, dass die gegebenen std::vector<LargeClass> &obj existiert immer während der Lebensdauer der Klasse Abc. Um dieses Problem zu lösen, ist eine andere Lösung zu verwenden shared_ptr:

class Abc 
     { 
    public: 
     Abc(boost::shared_ptr<std::vector<LargeClass>> obj) 
     { 
      pObj = obj; 
     } 
    boost::shared_ptr<std::vector<LargeClass> > pObj; 
    } 

Also meine Frage ist: Welche Lösung ist besser? Für mich bevorzuge ich das erste, aber es entspricht nicht den Regeln der objektorientierten Programmierung. Irgendwelche Vorschläge?

+1

Der Fall, dass ein vorinitialisierter Vektor an den Konstruktor übergeben wird, muss nicht teuer sein, wenn der Aufrufer std :: move (http://en.cppreference.com/w/cpp/utility/move) verwendet, wenn Übergeben sie an den Konstruktor – nate

+0

müssen diese Instanzen von 'LargeClass' unabhängig von' ABC' existieren oder kann 'ABC' das komplette Eigentum übernehmen? – user4581301

+0

In Ihrem Beispiel ist der Vektor der Eigentümer, und der Move-Konstruktor übergibt den Besitz von einem Vektor an den nächsten – nate

Antwort

1

den Schritt Konstruktor:

class Abc 
{ 
public: 
    Abc(std::vector<LargeClass> objTemp) : obj(std::move(objTemp)) {} 

private: 
    std::vector<LargeClass> obj; 
}; 

oder

class Abc 
{ 
public: 
    Abc(std::vector<LargeClass>&& objTemp) : obj(std::move(objTemp)) {} 

private: 
    std::vector<LargeClass> obj; 
}; 

Wenn LargeClass beweglich-only (nicht kopierbar), sind beide im Wesentlichen äquivalente Lösung.

Wenn LargeClass kopierbar ist, empfehle ich die zweite, die eine korrekte Verwendung erzwingen.

Ich schlage vor, den Kopierkonstruktor von LargeClass zu löschen, wenn Sie Kopie vermeiden wollen (und einen preiswerten Move-Konstruktor implementieren).

1

Statt

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp) 
     { 
      obj = objTemp; 
     } 
} 

Dies hat das Potenzial eines kopier Bau einer Quelle vector in objTemp, ein Standard-Konstrukt von obj, und die Kopie von objTemp in obj

Möglicherweise 2 Kopien und ein Standardkonstrukt. Yucky.

nehmen stattdessen die Vorteile der Member Initializer List

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> & objTemp):obj(objTemp) 
     { 
     } 
} 

Dieser Teil der Initialisierung eliminiert durch obj mit einem Verweis auf objTemp Kopie-Konstruktion. Die Angabe objTemp als Referenz eliminiert die Kopierkonstruktion von objTemp.

Es kann auch Leistungsvorteile zu diesem Trick:

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> objTemp):obj(std::move(objTemp)) 
     { 
     } 
} 

In diesem Fall objTemp ist kopier aufgebaut, wenn der Compiler dies zu tun für richtig hält, und zog dann in obj. Der Compiler kann dies möglicherweise im Nachhinein für große Einsparungen optimieren.

Wenn objTemp ist völlig entbehrlich, können Sie

class Abc 
{ 
    public: 
     Abc(std::vector<LargeClass> & objTemp):obj(std::move(objTemp)) 
     { 
     } 
} 

und den Inhalt objTemp in obj bewegen, können Sie den Kopiervorgang zu speichern. objTemp ist jetzt völlig leer. Wenn du es außerhalb von ABC brauchst, naja ... Scheiss dich.

Ich würde keinen gemeinsamen Zeiger verwenden, es sei denn ABC und andere beide haben Anspruch auf den Besitz von objTemp und haben inkompatible Bereiche.

Verwandte Themen