2016-02-10 9 views
5

Utilizzando la nuova sintassi di collocamento, dovrei essere in grado di fare qualcosa del genere:Come determinare se l'oggetto è stato collocato con nuova collocazione

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 

Ora supponiamo io faccio solo la prima linea, ma non la seconda . C'è un modo in cui è possibile determinare in codice se il buffer è stato assegnato in modo appropriato, ma nessun oggetto di tipo MyClass è stato ancora istanziato lì?

+2

Perché ne hai bisogno? Non sembra giusto. – ZDF

+0

@ ZDF Come risulta, mentre guardavo il problema più da vicino, probabilmente non lo faccio. Quindi la risposta alla tua domanda sembra abbastanza chiara: inesperienza ... :) – Bitrex

risposta

1

Codice originale:

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 

Per determinare in modo dinamico se il posizionamento new è stata eseguita informazioni su di esso deve essere memorizzato da qualche parte. La lingua non fornisce questo servizio. Quindi devi farlo tu stesso, in uno dei due possibili modi principali:

  • Memorizzare le informazioni nel buffer.
    In questo caso il buffer deve essere inizializzato in fase di allocazione. Per esempio. è sufficiente aggiungere () alla fine dell'espressione new. Altrimenti non c'è modo di garantire che il contenuto del buffer non assomigli ad un oggetto. Due sottocasi:
    1. Aggiungendo spazio per un flag nel buffer.
    2. Avendo la bandiera come membro dell'oggetto.
      Nel caso di una classe polimorfica ci sarà in pratica un puntatore vtable non zero, che può fungere da flag.
  • Memorizzare le informazioni esternamente.
    In questo caso, il buffer non deve essere inizializzato all'allocazione.Ci sono un miliardo più alcune possibilità, tra cui
    1. Una semplice variabile bool.
    2. Una raccolta di puntatori a tutti questi oggetti.
    3. Un segnale udibile emesso da uno scimpanzé, che verrà successivamente interrogato.
4

La lingua non fornisce alcun meccanismo incorporato per fornire tali informazioni, almeno nessuna che io conosca. Dovrai aggiungere il tuo codice contabile per tenere traccia di tali informazioni.

1

È possibile mantenere una tabella static di valori di puntatore this muta nei costruttori e nel distruttore su MyClass. Quindi controllare questo valore con un valore particolare di buffer quando è necessario.

Non dimenticare di considerare le ripercussioni della semantica del movimento. Sarà complicato avere ragione.

2

Per scopi di debug, è possibile aggiungere un membro speciale signature-MyClass e impostarne il valore a una costante

class MyClass { 
    public: 
     MyClass() : signature(762347562374) {} 
     bool isValidSignature() const { return signature==762347562374; } 
    private: 
     unsigned long long signature; 
     <other members> 
}; 

Poi, controllato nel modo seguente:

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 
if (my_class->isValidSignature()) 
    <this means that the object has been allocated correctly, with a high probability> 
} 

si può mettere tutto ciò che è relativo alla firma, all'interno di un opportuno #ifdef in modo che venga eseguito solo in modalità di debug.

+0

Perché dovremmo usare un approccio statistico quando una bandiera produce un comportamento garantito? –

+0

@ Cheersandhth.-Alf Sembra che ci sia qualche soluzione banale al problema di cui stai parlando. Non capisco; forse dovresti aggiungere una risposta per spiegare cosa intendi con "una bandiera". – anatolyg

+0

Odio le classi che hanno una dimensione diversa (maggiore) nei build di debug –

1

Non senza tracciamento da soli.

Una soluzione potrebbe essere quella di creare un wrapper attorno a std::allocator.

template<class T> 
class MyAllocator 
{ 
public: 
    T* allocate(std::size_t count = 1) 
    { 
     return allocator_.allocate(count); 
    } 

    template<class... Args> 
    void construct(T* ptr, Args&&... args) 
    { 
     allocator_.construct(ptr, std::forward<Args>(args)...); 
     allocated_ = true; 
    } 

    bool IsAllocated() const 
    { 
     return allocated_; 
    } 

private: 
    std::allocator<T> allocator_; 
    bool allocated_; 

}; 
+0

Come si confronta questo solo con una variabile 'bool' direttamente? –

+0

Ho solo pensato che fosse un bel modo per concludere le cose. –

Problemi correlati