12 Stimmen

Effiziente Alternativen für die Offenlegung einer Sammlung

Welche Alternativen habe ich in C++, um eine Sammlung unter dem Gesichtspunkt der Leistung und der Datenintegrität darzustellen?

Mein Problem ist, dass ich eine interne Liste von Daten an den Aufrufer zurückgeben möchte, aber ich möchte keine Kopie erzeugen. Somit bleibt mir nur die Möglichkeit, entweder einen Verweis auf die Liste oder einen Zeiger auf die Liste zurückzugeben. Ich bin jedoch nicht verrückt danach, den Aufrufer die Daten ändern zu lassen, ich möchte ihn die Daten nur lesen lassen.

  • Muss ich zwischen Leistung und Datenintegrität wählen?
  • Wenn ja, ist es generell besser, einen Weg einzuschlagen, oder ist dies vom Einzelfall abhängig?
  • Gibt es andere Alternativen?

7voto

David Joyner Punkte 21019

Oftmals möchte der Aufrufer nur Zugriff, um die Sammlung zu durchlaufen. Nehmen Sie eine Seite aus dem Buch von Ruby und machen Sie die Iteration zu einem privaten Aspekt Ihrer Klasse.

#include <algorithm>
#include <boost/function.hpp>

class Blah
{
  public:
     void for_each_data(const std::function<void(const mydata&)>& f) const
     {
         std::for_each(myPreciousData.begin(), myPreciousData.end(), f);
     }

  private:
     typedef std::vector<mydata> mydata_collection;
     mydata_collection  myPreciousData;
};

Mit diesem Ansatz geben Sie nichts über Ihre Interna preis, d.h. dass Sie sogar haben eine Sammlung.

1 Stimmen

Ich weiß, dies ist eine alte Antwort, aber ich mache das jetzt mit std::function: void for_each_data(const std::function<void(const mydata&)>& f) const;

0 Stimmen

@JoBates Ich verwende C++ nicht mehr täglich, bitte bearbeiten Sie meine Antwort, um sie auf den neuesten Stand zu bringen!

5voto

Shog9 Punkte 151504

RichQs Antwort ist eine vernünftige Technik, wenn Sie ein Array, einen Vektor usw. verwenden.

Wenn Sie eine Sammlung verwenden, die nicht durch Ordinalwerte indiziert ist... oder denken, dass Sie müssen möglicherweise irgendwann in naher Zukunft... dann sollten Sie vielleicht in Erwägung ziehen, Ihre eigenen Iterator-Typen und die zugehörigen begin() / end() Methoden:

class Blah
{
public:
   typedef std::vector<mydata> mydata_collection;
   typedef myDataCollection::const_iterator mydata_const_iterator;

   // ...

   mydata_const_iterator data_begin() const 
      { return myPreciousData.begin(); }
   mydata_const_iterator data_end() const 
      { return myPreciousData.end(); }

private:
   mydata_collection  myPreciousData;
};

...die Sie dann wie gewohnt verwenden können:

Blah blah;
for (Blah::mydata_const_iterator itr = blah.data_begin();
   itr != blah.data_end();
   ++itr)
{
   // ...
}

3voto

Ben Collins Punkte 20125

Vielleicht so etwas wie das hier?

const std::vector<mydata>& getData()
{
  return _myPrivateData;
}

Der Vorteil ist, dass es sehr, sehr einfach ist und so sicher wie C++. Man kann es casten, wie RobQ vorschlägt, aber es gibt nichts, was man tun könnte, um jemanden daran zu hindern, wenn man nicht kopiert. Hier müsstest du Folgendes verwenden const_cast was ziemlich leicht zu erkennen ist, wenn man darauf achtet.

Mit Iteratoren kann man in etwa das Gleiche erreichen, aber es ist komplizierter. Der einzige zusätzliche Vorteil der Verwendung von Iteratoren hier (die ich mir vorstellen kann) ist, dass Sie eine bessere Kapselung haben können.

2voto

Die Verwendung von const reference oder shared pointer hilft nur, wenn sich der Inhalt der zugrunde liegenden Sammlung im Laufe der Zeit nicht ändert.

Überlegen Sie sich Ihr Design. Muss der Aufrufer das interne Array wirklich sehen? Können Sie den Code so umstrukturieren, dass der Aufrufer dem Objekt mitteilt, was es mit dem Array tun soll? Wenn der Aufrufer z. B. beabsichtigt, das Array zu durchsuchen, könnte das Eigentümerobjekt dies tun?

Sie können einen Verweis auf den Ergebnisvektor an die Funktion übergeben. Bei einigen Compilern kann dies zu geringfügig schnellerem Code führen.

Ich würde empfehlen, zuerst ein Redesign zu versuchen, dann eine saubere Lösung zu wählen und schließlich die Leistung zu optimieren (falls nötig).

2voto

JohnMcG Punkte 8423

Ein Vorteil der Lösungen von @Shog9 und @RichQ ist, dass sie den Client von der Implementierung der Sammlung entkoppeln.

Wenn Sie sich entscheiden, die Art Ihrer Sammlung zu ändern, werden Ihre Kunden weiterhin funktionieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X