2017-02-09 2 views
0

Je fais référence à Refbase.h, Refbase.cpp et StrongPointer.hpointeur fort natif Android vs std :: shared_ptr

Dans la mise en œuvre Android du pointeur fort, un objet à base forte pointeur doit hériter refbase-à-dire

sp<TheClass> theObj // TheClass must inherit from class RefBase 

Cette exigence peut être vu dans le code pour l'une des méthodes de sp:

template<typename T> sp<T>& sp<T>::operator =(T* other) { 
    if (other != NULL) { 
     other->incStrong(this); 
    } 
    if (mPtr != NULL) { 
     mPtr->decStrong(this); 
    } 
    mPtr = other; 
    return *this; 
} 

en commande pour appel à incStrong ou decStrong pour ne pas échouer. . . other et mPtr doit avoir hérité RefBase

QUESTION

Pourquoi sp mis en œuvre de telle sorte que l'obj qu'il est nécessaire de gérer est d'être un enfant de RefBase? Il n'y a même pas moyen de faire respecter cette exigence lors de la compilation ou même de l'exécution. (Eh bien peut-être if(type()...)

Std library doesn't have such a requirement

...
Une fois encore la pensée, est la réponse que cette offre une flexibilité?
Si oui, comment cela offre-t-il de la flexibilité?

Répondre

0

Il enregistre une allocation de mémoire. Lorsque vous écrivez:

std::shared_ptr<Foo> pFoo{new Foo(bar)}; 

pFoo a en fait un pointeur vers une structure de données partagées (allouées sur le tas), qui a les compteurs de référence, et le pointeur sur l'objet Foo réelle. En créant des objets à partir de RefBase, vous pouvez intégrer les comptages de références dans l'objet lui-même (en enregistrant l'allocation de mémoire supplémentaire). Fait intéressant, à partir de C++ 11, vous pouvez éviter l'allocation de mémoire supplémentaire en utilisant std::make_shared<Foo> qui fera une seule allocation de mémoire et construira la structure de données partagée et l'objet Foo.

Le fait qu'il n'y ait pas de vérification de temps de compilation de la dérivation de RefBase est la négligence. m_ptr aurait dû être déclaré RefBase *m_ptr, puis operator * (etc) aurait dû faire une static_cast à T*. En fait, j'aurais probablement fait sp<T> hériter de sp_base qui avait les opérateurs de comparaison comme public, et les autres fonctions comme protégées.

Modifier

A la réflexion, il est un peu de temps la vérification de la compilation. Si T n'a pas de membre incStrong, la compilation échouera, et il presque certainement pas, sauf si elle dérive de RefBase. Je pense toujours convertir un T* à un RefBase* aurait été un mieux vérifier, mais celui qui est là est probablement assez bon.

+2

Etes-vous sûr que votre exemple est légal pour 'shared_ptr'? [L'opérateur d'affectation ne prend que des pointeurs spéciaux.] (Http://www.cplusplus.com/reference/memory/shared_ptr/operator=/) Pour class'sp', cette affectation ** est ** légale. – Adrian

+0

Je ne montre pas d'opérateur d'affectation - J'ai montré une initialisation. Si vous voulez faire une affectation avec shared_ptr, il faudrait que ce soit: 'pFoo = shared_ptr (nouveau Foo (bar));' –

+0

... et c'est l'autre avantage d'un pointeur intrusif. (et vous n'avez pas à jouer à des jeux stupides avec 'shared_from_this'). –

0

Il vous permet automatiquement de créer sp à partir de n'importe quel objet implémentant RefBase, tandis que pour le pointeur partagé, vous pouvez vous tirer dans le pied tout en essayant de placer le pointeur brut dans le point partagé.

Ainsi, alors que pour shared_ptr vous pourriez avoir besoin ceci: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

pour sp vous pouvez passer presque sans risque pointeur brut à sp contructor.