web-dev-qa-db-fra.com

Différence entre `const shared_ptr <T>` et `shared_ptr <const T>`?

J'écris une méthode d'accès pour un pointeur partagé en C++ qui ressemble à ceci:

class Foo {
public:
    return_type getBar() const {
        return m_bar;
    }

private:
    boost::shared_ptr<Bar> m_bar;
}

Donc, pour supporter la const-ness de getBar(), le type de retour doit être un boost::shared_ptr Qui empêche la modification du Bar auquel il pointe. Mon suppose est que shared_ptr<const Bar> Est le type que je veux revenir pour le faire, alors que const shared_ptr<Bar> Empêcherait la réaffectation du pointeur lui-même pour pointer vers un autre Bar mais permet la modification du Bar vers lequel il pointe ... Cependant, je ne suis pas sûr. J'apprécierais que quelqu'un qui en soit sûr puisse soit confirmer cela, soit me corriger si je me suis trompé. Merci!

98
Dave Lillethun

Vous avez raison. shared_ptr<const T> p; est similaire à const T * p; (ou équivalent, T const * p;), c’est-à-dire que l’objet pointé est const alors que const shared_ptr<T> p; est similaire à T* const p; ce qui signifie que p est const. En résumé:

shared_ptr<T> p;             ---> T * p;                                    : nothing is const
const shared_ptr<T> p;       ---> T * const p;                              : p is const
shared_ptr<const T> p;       ---> const T * p;       <=> T const * p;       : *p is const
const shared_ptr<const T> p; ---> const T * const p; <=> T const * const p; : p and *p are const.

Il en va de même pour weak_ptr et unique_ptr.

138
Cassio Neri

boost::shared_ptr<Bar const> empêche la modification de l'objet Bar par le pointeur partagé. En tant que valeur de retour, le const dans boost::shared_ptr<Bar> const signifie que vous ne pouvez pas appeler une fonction non-const sur le temporaire renvoyé; s’il s’agissait d’un pointeur réel (par exemple, Bar* const), il serait complètement ignoré.

En général, même ici, les règles habituelles s’appliquent: const modifie ce qui le précède: in boost::shared_ptr<Bar const>, le Bar; dans boost::shared_ptr<Bar> const, c'est l'instanciation (l'expression boost::shared_ptr<Bar> qui est const.

2
James Kanze
#Check this simple code to understand... copy-paste the below code to check on any c++11 compiler

#include <memory>
using namespace std;

class A {
    public:
        int a = 5;
};

shared_ptr<A> f1() {
    const shared_ptr<A> sA(new A);
    shared_ptr<A> sA2(new A);
    sA = sA2; // compile-error
    return sA;
}

shared_ptr<A> f2() {
    shared_ptr<const A> sA(new A);
    sA->a = 4; // compile-error
    return sA;
}

int main(int argc, char** argv) {
    f1();
    f2();
    return 0;
}
1
vivek2k6

J'aimerais une démonstration simple basée sur la réponse de @Cassio Neri:

#include <memory>

int main(){
    std::shared_ptr<int> i = std::make_shared<int>(1);
    std::shared_ptr<int const> ci;

    // i = ci; // compile error
    ci = i;
    std::cout << *i << "\t" << *ci << std::endl; // both will be 1

    *i = 2;
    std::cout << *i << "\t" << *ci << std::endl; // both will be 2

    i = std::make_shared<int>(3);
    std::cout << *i << "\t" << *ci << std::endl; // only *i has changed

    // *ci = 20; // compile error
    ci = std::make_shared<int>(5);
    std::cout << *i << "\t" << *ci << std::endl; // only *ci has changed

}
0
Jónás Balázs