Frage

Ich bin C ++ mit der OpenCV-Bibliothek, die eine Bibliothek Bildverarbeitung ist allerdings, dass für diese Frage nicht relevant ist. Zur Zeit habe ich eine Design-Entscheidung zu treffen.

OpenCV, eine C-Bibliothek ist, hat seine Datenstrukturen (wie CvMat) als structs erklärt. Um sie zu erstellen, verwenden Sie Funktionen wie cvCreateMat, und sie freizugeben, verwenden Sie Funktionen wie cvReleaseMat. Als ein C ++ Programmierer, habe ich eine besondere cv_scoped Klasse, die cvReleaseMat automatisch nennen würde, wenn es außerhalb des Bereichs ging (wie boost::scoped_ptr).

Was ich zu realisieren ist jetzt, dass ich wünsche, ich auto_ptr und shared_ptr in Fällen, als auch nutzen könnte. Ich fühle mich einfach, dass das Schreiben von Code für meine eigene cv_auto_ptr und cv_shared_ptr Klassen eine schlechte Idee wäre, nicht eine Verschwendung von Zeit zu erwähnen. Also ich habe nach Lösungen zu suchen, und ich habe mit drei Möglichkeiten kommen.

Erste , ich die cv_scoped Klasse verwendet, konnte ich bereits gemacht habe. Ich würde es umbenennen, um cv_ptr und dann intelligente Zeiger verwenden wie so: std::auto_ptr<cv_ptr>. Die ärgerliche Sache über dieses ist aber, ich immer zu dereferenzieren haben würde zweimal:

std::auto_ptr<cv_ptr> matrix(cv_ptr(cvCreateMat(320, 240, CV_32FC3)));
cvPow(matrix.get()->get()); // one get for the auto_ptr, one for the cv_ptr

Ich weiß, es sieht aus wie ich eine implizite Konvertierung erklären konnte, aber ich kann nicht wirklich - die meisten von OpenCV Funktionen haben den Parameter void * - also keine implizite Konvertierung aufgerufen werden würde. Ich möchte wirklich eine Art und Weise, dies zu tun, wo ich nicht die doppelte Dereferenzierung zu tun hatte.

Zweite , kann ich irgendwie überschreiben operator delete. Ich will nicht die globalen Betreiber außer Kraft setzen löschen, weil ich nur wollen würde dies zu CvMat (und einige andere) Arten anzuwenden. Allerdings kann ich die Bibliothek nicht ändern, so kann ich nicht operator delete zur CvMat Struktur hinzuzufügen. Also ich weiß nicht, wie das funktionieren würde.

Dritter , konnte ich nur meine eigenen auto_ptr, scoped_ptr umschreiben, und shared_ptr. Sie sind nicht große Klassen, damit es nicht zu schwierig sein würde, aber ich fühle mich einfach so schlechtes Design. Wenn ich dies tun würde, würde ich wahrscheinlich etwas in diese Richtung tun:

class cv_auto_ptr {
public:
  cv_auto_ptr();
  ~cv_auto_ptr();

  // each method would just be a proxy for the smart pointer
  CvMat* get() { return this->matrix_.get()->get(); }
  // all the other operators/methods in auto_ptr would be the same, you get the idea

private:
  auto_ptr<cv_ptr> matrix_; // cv_ptr deletes CvMat properly
}

Was würden Sie in meiner Situation tun? Bitte helfen Sie mir diese eine herausfinden.

War es hilfreich?

Lösung

Die auto_ptr sind für RAII auf C ++ Klasse wirklich entwickelt, um mit Konstrukten / Destruktoren Sie drängen ihre Verwendungen hier Dinge, die sie sollten wahrscheinlich nicht verwendet werden (aber können).

Wie auch immer don'y Sie wollen in der Lage sein, Ihre C ++ Objekt, als ob es ein normaler Stapel Variable war, ohne jedes Mal die dynamische Zuweisung?

Die Standard-Lösung für Ihr Problem ist ein Wrapper mit Konstruktor / Destruktor zu erstellen.
Aber, um es durch die C-Funktionen nutzbar zu machen nur einen internen Cast-Operator hinzufügen, so dass es automatisch auf magische Weise selbst an das C-Objekt konvertiert zurück, wenn auf eine C-Funktion übergibt

eine Wrapper-Klasse schreiben.

class Mat
{
    CvMat* impl;
    public:
        Mat(/* Constructor  Arguments */)
        {
            impl = cvCreateMat(/* BLAH */);
        }
        ~Mat()
        {
            cvReleaseMat(impl);
        }
        operator CvMat*()
        {   // Cast opertator. Convert your C++ wrapper object into C object
            // when you use it with all those C functions that come with the
            // library.

            return impl;
        }
};

void Plop(CvMat* x)
{   // Some C function dealing with CvMat
}

int main()
{                            // Don't need to dynamically allocate
    Mat                  m;  // Just create on the stack.
    Plop(m);                 // Call Plop directly

    std::auto_ptr<Mat>   mP(new Mat);
    Plop(*mP);
}

Andere Tipps

Ein Ansatz, die Sie berücksichtigen könnte, ist die Tatsache genutzt, dass std::tr1::shared_ptr die Funktionalität eines benutzerdefinierten deleter zur Verfügung stellen muss. Ich habe keine Vertrautheit mit OpenCV so aus mir Folgern was du geschrieben hast.

struct CvMatDeleter
{
    void operator( CvMat* p ) { cvReleaseMat( p ) ; }
};

void test()
{
    std::tr1::shared_ptr< CvMat > pMat( cvCreateMat(320, 240, CV_32FC3), CvMatDeleter() );
    // . . .
}

Da die deleter ist Speicher in dem freigegebenen Zeiger können Sie einfach es als normal verwenden und wenn der gemeinsame Rohzeiger muss schließlich gelöscht wird, wird cvReleaseMat nach Bedarf aufgerufen werden. Beachten Sie, dass auto_ptr und scoped_ptr sind viel leichte Klassen also nicht die Funktionalität für benutzerdefinierte Löscher haben, aber wenn man für den kleinen Overhead bereit ist, dann kann shared_ptr an ihrer Stelle verwendet werden.

Wenn alles, was Sie kümmern uns um die Sicherheit Ausnahme ist, tun dies jedes Mal wenn Sie Matrizes verwenden:

void f() {
    try {
        CvMat* mat = cvCreateMat(320, 240, CV_32FC3));
        // ...
    } catch(...) {
        cvReleaseMat(mat);
        throw;
    }
    cvReleaseMat(mat);
}

Wenn auf der anderen Seite, Sie wollen eine gesund Lösung, geht die extra Meile und schreibt einen vollständigen Wrapper.

namespace cv {

class Mat {
public:
    enum Type { /* ... */ };
    Mat(int w, int h, Type type) {
        impl = cvCreateMat(w, h, intFromType(type));
    }

    ~Mat() {
        cvReleaseMat(impl);
    }

    void pow() { // wrap all operations
        cvPow(impl);
    }

private:
    CvMat* impl;
};

}

Möchten Sie den Mittelweg, ein Sammelsurium von allgemeinem intelligentem Zeiger verwenden und „cv_ptrs“ klingt wie ein Rezept für Kopfschmerzen und eine unnötige Komplikation.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top