const & oder lieber Pointer?



  • Hallo 🙂

    Ich hab zwei Fragen, die eine ist, welcher der folgenden Möglichkeite ich benutzen sollte:

    void MachWas(const Typ& object);
    

    oder

    void MachWas(Typ *ptrObject);
    

    Ich habe gelesen, das bei ersterer Variante trotz der Referenz ziemlich oft kopiert wird?? Das wäre ungünstig, was meint ihr?

    2.)
    Folgendes ist ja möglich:

    MeinTyp object = { 0 };
    

    Wenn nun object ein Klassenattribut ist, geht das nicht mehr:

    // Im Konstruktor
    object = { 0 };
    

    Wie lautet die Syntax?



  • pazoA schrieb:

    Ich habe gelesen, das bei ersterer Variante trotz der Referenz ziemlich oft kopiert wird?? Das wäre ungünstig, was meint ihr?

    Da hast du was falsches gelesen. Wenn die Übergabe eines NULL-Pointers keinen Sinn macht, nehme ich ausschließlich eine Referenz.

    Wie lautet die Syntax?

    Initialisierungen macht man im Konstruktor über die Initialisierungsliste, was du aber vorhast geht (noch) nicht!



  • pazoA schrieb:

    Ich habe gelesen, das bei ersterer Variante trotz der Referenz ziemlich oft kopiert wird?? Das wäre ungünstig, was meint ihr?

    Verbrenn' die Quelle. Wann immer möglich (außer für die Builtin-Datentypen (short, int, long, unsigned, double, float, void*) solltest du als konstante Referenz übergeben.

    pazoA schrieb:

    Folgendes ist ja möglich:

    MeinTyp object = { 0 };
    

    Nein, nur wenn MeinTyp ein POD-Struct mit einem Member eines integralen oder Zeigertypen ist.

    pazoA schrieb:

    Wenn nun object ein Klassenattribut ist, geht das nicht mehr:

    // Im Konstruktor
    object = { 0 };
    

    Wie lautet die Syntax?

    Es gibt keine. Das Erste ist ein Konstruktor, das zweite ist eine Zuweisung. Das sind elementar verschiedene Dinge. Abgesehen davon solltest du sowieso einen anständigen Konstruktor definieren.



  • pazoA schrieb:

    void MachWas(const Typ& object);
    

    oder

    void MachWas(Typ *ptrObject);
    

    Die beiden Varianten haben kaum etwas miteinander zu tun. Man schaue einfach mal auf die "const-Situation"...

    Gruß,

    Simon2.



  • rüdiger schrieb:

    Wie lautet die Syntax?

    Initialisierungen macht man im Konstruktor über die Initialisierungsliste, was du aber vorhast geht (noch) nicht!

    Du hast genau das getroffen was ich meinte 🙂
    Also muss ich jedes Attribut des Klassenattributs explizit mit 0 initialisieren? 😕



  • Nope. Du verpasst der Klasse des Klassenattributs einfach auch einen ctor:

    class A
    {
    public:
        A();
        A(int a, int b, int c)
          :  m_a(a),
             m_b(b),
             m_c(c)
        {
        }
    
        int m_a;
        int m_b;
        int m_c;
    };
    
    class B
    {
    public:
        B()
           :  m_a(0, 0, 0),
              m_i(0)
        {
            // geht auch so (vorausgesetzt A hat einen operator =, und der wird defaultmässig vom compiler erstellt wenn man es nicht irgendwie verhindert)
            m_a = A(1, 2, 3);
        }
    
    private:
       A m_a;
       int m_i;
    };
    

  • Mod

    Die Benutzung eines eigenen ctors ist eine Möglichkeit, allerdings ist die betreffende Klasse dann kein Aggregat und schon gar kein POD-struct mehr. Zudem hat man diese Möglichkeit nicht, wenn man etwa fremde klassen aus irgendwelchen Bibliotheken benutzt. Man kann die Initialisierung auch mit einer benannten Funktion durchführen:

    struct A
    {
        int m_a;
        int m_b;
        int m_c;
    };
    inline A makeA(int a, int b, int c)
    {
        A x = { a, b, c };
        return x;
    }
    
    class B
    {
    public:
        B()
           :  m_a(makeA(0, 0, 0)),
              m_i(0)
        {
              // oder
              m_a = makeA(1, 2, 3);
        }
    
    private:
       A m_a;
       int m_i;
    };
    

    Ein Compiler, der überhaupt NRVO beherrscht, wird hier alle Kopien eliminieren.

    Daraus kann man ein schönes Idiom machen:

    template <typename T, typename... Args>
    T make_aggregate(Args... args)
    {
        T x = { args... };
        return x;
    }
    

    (wobei das bei C++0x möglicherweise gar nicht mehr nötig ist?)


Anmelden zum Antworten