2016-03-21 22 views
8

Welcher ist der korrekte Weg, um die const Korrektheit einer Klasse zu seinen spitzen Mitgliedern zu erweitern? In dem Beispielcode, wird die konstante Version der Methode get ein std::shared_ptr erstellen, deren Referenzzähler ist das gleiche wie das interne Mitglied m_b, oder beginnt es wieder von 0 zu zählen?Gemeinsame Zeiger und const Korrektheit

class A 
{ 
    std::shared_ptr<B> m_b; 

public: 

    std::shared_ptr< const B > get_b() const 
    { 
     return m_b; 
    } 

    std::shared_ptr<B> get_b() 
    { 
     return m_b; 
    } 
} 
+0

Vielleicht möchten Sie implementieren auch 'get_const_b()', analog Methoden 'CBEGIN()' und 'cend()' von Standardcontainern (http://en.cppreference.com/w/cpp/container/vector/begin). – filipos

Antwort

7

shared_ptr wird immer Referenzzähler erhalten, wenn Sie von einem anderen shared_ptr zu konstruieren; Die einzige Möglichkeit, es zu verwenden unsicher ist aus einem rohen Zeiger zu konstruieren: shared_ptr<...>(my_ptr.get()) // don't do this.

Sie könnten auch interessiert sein an der propagate_const Wrapper, der in der Library Fundamentals TS v2 ist, so wird wahrscheinlich in Ihrer Implementierung bald verfügbar sein.

0

Die Antwort kann abgeleitet werden, indem einige Tests mit use_count() durchgeführt werden.

Beachten Sie auch, wie Verfahren Auflösung nicht ganz klar sein:

class B {}; 

class A { 
    std::shared_ptr<B> m_b; 

public: 
    A() { m_b = std::make_shared<B>(); } 

    std::shared_ptr<const B> get_b() const { 
    std::cout << "const" << std::endl; 
    return m_b; 
    } 

    std::shared_ptr<B> get_b() { 
    std::cout << "non const" << std::endl; 
    return m_b; 
    } 
}; 

int main(int, char **) { 

    A a; 

    std::shared_ptr<B> b = a.get_b(); 

    std::cout << b.use_count() << std::endl; 

    std::shared_ptr<const B> cb = a.get_b(); 

    std::cout << cb.use_count() << std::endl; 

    const A &a_const_ref = a; 

    std::shared_ptr<const B> ccb = a_const_ref.get_b(); 

    std::cout << ccb.use_count() << std::endl; 

    return 0; 
} 

Ausgang:

non const 
2 
non const 
3 
const 
4 
+0

Bitte, könnten Sie hier klären, was genau hier nicht intuitiv ist und welche Art von Fallstrick Sie erwarten? Die Ergebnisse erscheinen mir logisch und sicher. – filipos

+0

Man könnte denken, dass der zweite Aufruf von 'get_b()' in die 'const'-Version aufgelöst wird. Außerdem wird derselbe ref-Zähler um den dritten Aufruf inkrementiert, was die Antwort auf die Frage selbst ist. –

+0

Ich habe meine Antwort ein wenig umformuliert, ich wollte nicht so viel Wert auf die Fallstricke legen. –