Classe come handle di risorse e copia non valida

1

Sto leggendo il libro di Bjarne Stroustrup intitolato "A tour of C ++".

La seguente sezione mi confonde:

When a class is a resource handle – that is, when the class is responsible for an object accessed through a pointer – the default member wise copy is typically a disaster.

Member wise copy would violate the resource handle’s invariant. For example, the default copy would leave a copy of a Vector referring to the same elements as the original:

void bad_copy(Vector v1)
{
    Vector v2 = v1;
    // copy v1’s representation into v2
    v1[0] = 2;
    // v2[0] is now also 2!
    v2[1] = 3;
    // v1[1] is now also 3!
}

In particolare, non capisco quanto segue:

  1. Quando Vector v1 viene passato come valore, non come riferimento, come mai v2 e v1 si riferiscono entrambi allo stesso indirizzo di memoria.

  2. Che cosa significa la frase "Quando una classe è un handle di risorsa" significa?

posta bhaskarc 12.01.2015 - 16:18
fonte

2 risposte

3

What does the sentence "When a class is a resource handle" mean?

Significa che i membri delle classi non sono in realtà i dati interessanti, ma solo puntatori, riferimenti o altri tipi di handle per questo.
Pertanto, copiarli non copia i dati interessanti, il che significa che una copia membro-per-membro è completamente sbagliata.

Che risponde anche alla tua altra domanda.

Per assicurarti di copiare correttamente le cose, dai un'occhiata alla "regola dei tre" e alla sua evoluzione "la regola del cinque".
Sebbene tu abbia la scelta (che è quasi sempre), segui "la regola dello zero".

    
risposta data 12.01.2015 - 16:42
fonte
2

Risponderò in ordine inverso, per renderlo più chiaro.

  1. What does the sentence "When a class is a resource handle" means ?

Una risorsa può essere qualsiasi cosa, da un pezzo di memoria, fino a un file. Gestire una risorsa significa aprire una risorsa, fornirne l'accesso e chiuderla alla fine.

Ad esempio, la prossima classe assegnerà un po 'di memoria nel costruttore, la rilascia in distruttore e fornirà un metodo per accedervi (ho usato le funzioni c di proposito):

class MemoryHandler
{
public:
    MemoryHandler() : mem( malloc(10) )
    {
    }
    ~MemoryHandler()
    {
        free(mem);
    }
    void* Access(){ return mem;}
    void* mem;
};

Quindi, cosa succede quando copi questo oggetto? Se sei fortunato, il programma si bloccherà.

void DoSomething( MemoryHandler m )
{
  // do something
}

MemoryHandler m;
DoSomething( m );

Perché si blocca? Poiché la funzione DoSomething prenderà l'oggetto in base al valore, creerà un nuovo oggetto utilizzando il costruttore di copie, che verrà rilasciato alla fine dell'ambito. Il costruttore di copie predefinito copia semplicemente il puntatore. Pertanto, la causa del crash sarà la doppia versione di memoria.

Il costruttore di copie predefinito assomiglia a questo:

MemoryHandler( const MemoryHandler& object ) : mem( object.mem )
{
}

Come risolvere questo particolare problema, dipende da ciò di cui hai bisogno. Visualizza std::shared_ptr se vuoi rendere la classe copiabile, o std::unique_ptr per rendere la tua classe mobile.

  1. When Vector v1 is passed as a value, not as a reference, how come v2 and v1 both refer to the same memory address.

Non hai detto che cos'è vector , ma presumo che sia simile nell'esempio precedente.

Per risolvere il tuo problema, scopri cosa Regola di cinque è, e applicalo.

    
risposta data 12.01.2015 - 18:08
fonte

Leggi altre domande sui tag