2012-04-23 16 views
5

Quando si inizializza una variabile membro shared_ptr:Inizializzazione della variabile membro shared_ptr, nuova vs make_shared?

// .h 
class Customer 
{ 
public: 
    Customer(); 

private: 
    std::shared_ptr<OtherClass> something_; 
} 

// .cpp 
Customer(): 
    something_(new OtherClass()) 
{ 
} 

vs.

Customer(): 
    something_(std::make_shared<OtherClass>()) 
{ 
} 

è la versione make_shared ammessi? Mi sembra sempre di vedere la prima versione, che è preferibile?

+4

Herb Sutter ha appena scritto un GOTW su questo. Vedi [this] (http://herbsutter.com/gotw/_103/) e controlla anche [un problema] (http://lanzkron.wordpress.com/2012/04/22/make_shared-almost-a-silver -bullet /) che Herb non dichiara esplicitamente. –

+0

@RSamuelKlatchko - Un link aggiornato per il primo link che hai fornito nel tuo account utilizza https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ –

risposta

11

Le uniche volte in cui è make_sharednon permesso sono:

  1. Se stai ricevendo un puntatore nudo assegnato da qualcun altro e riporlo in shared_ptr. Questo è spesso il caso quando si interfaccia con le API C.
  2. Se il costruttore che si desidera chiamare non è pubblico (make_shared può chiamare solo costruttori pubblici). Questo può accadere con le funzioni di fabbrica, in cui si desidera forzare gli utenti a creare l'oggetto dalla fabbrica.

    Tuttavia, ci sono modi per aggirare questo. Invece di avere un costruttore privato, avere un costruttore pubblico. Ma fare in modo che il costruttore prenda un tipo con può essere costruito solo da chi ha accesso privato alla classe. In questo modo, le uniche persone che possono chiamare make_shared con quel tipo di oggetto sono quelle con accesso privato alla classe.

Quindi sì, puoi farlo.

+0

Per quanto riguarda il problema dell'amicizia, c'è qualche menzione nello standard della funzione particolare da utilizzare come amici? Potrei immaginare qualche implementazione che deleghi questo lavoro alle funzioni di aiuto ... –

+0

@MatthieuM .: Mi stavo chiedendo la stessa cosa, ed è per questo che ho detto "potrebbe essere in grado". Ho chiesto a comp.std.C++; vedremo cosa hanno da dire al riguardo. In caso contrario, penso che potrebbe creare un rapporto decente sui difetti. –

3

In questo caso, l'utilizzo di make_shared non è consentito solo, ma è preferibile utilizzarlo. Se usi new, allocherà memoria per il tuo Cliente da qualche parte e poi memoria per il tuo shared_ptr da qualche altra parte, memorizzando sia i riferimenti forti che quelli deboli (per puntatori deboli e puntatori condivisi). Se usi lo make_shared, avresti solo un posto in memoria con tutto e quindi solo uno nuovo.

Non sono sicuro di essere stato veramente chiaro, questo era lo scopo dello GotW #103, leggerlo, è ben spiegato lì.

Problemi correlati