2016-03-21 51 views
8

Qual è il modo corretto per estendere la correttezza di const di una classe ai relativi membri appuntiti? Nel codice di esempio, la versione costante del metodo get crea un std::shared_ptr il cui contatore di riferimento è lo stesso del membro interno m_b o sta ricominciando a contare da 0?Puntatori condivisi e correttezza const

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

Si potrebbe desiderare di implementare anche 'get_const_b()', analogo a metodi 'CBEGIN()' e 'cend()' dei contenitori standard (http://en.cppreference.com/w/cpp/container/vector/begin). – filipos

risposta

7

shared_ptr sarà sempre conservare i conteggi di riferimento quando si costruisce da un altro shared_ptr; l'unico modo per usarlo senza errori consiste nel costruire da un puntatore raw: shared_ptr<...>(my_ptr.get()) // don't do this.

Potresti anche essere interessato al wrapper propagate_const, che si trova nella Base di libreria TS v2, quindi sarà probabilmente disponibile nella tua implementazione abbastanza presto.

0

La risposta può essere dedotta facendo alcuni test con use_count().

noti anche come risoluzione metodo potrebbe essere non del tutto ovvia:

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; 
} 

uscita:

non const 
2 
non const 
3 
const 
4 
+0

Per favore, potresti chiarire che cosa è esattamente contro-intuitivo qui, e che tipo di trappola ti aspetti? I risultati mi sembrano abbastanza logici e sicuri. – filipos

+0

Si potrebbe pensare che la seconda chiamata a 'get_b()' risolva la versione 'const'. Inoltre, lo stesso contatore ref viene incrementato dalla terza chiamata, che è la risposta alla domanda stessa. –

+0

Ho riformulato la mia risposta un po ', non intendevo dare molta enfasi alle insidie. –