Domanda

In C ++ const un oggetto stack allocato può essere dichiarato:

const Class object;

dopo che il tentativo di chiamare un metodo non const su tale scopo viene comportamento indefinito:

const_cast<Class*>( &object )->NonConstMethod(); //UB

Può un oggetto heap allocata essere const con le stesse conseguenze? Insomma è possibile che il seguente:

const Class* object = new Class();
const_cast<Class*>( object )->NonConstMethod(); // can this be UB?

è anche un comportamento indefinito?

È stato utile?

Soluzione

Sì. E 'legale per costruire e distruggere un oggetto const mucchio. Come con altri oggetti const, i risultati di manipolazione come un oggetto non const (ad esempio attraverso un const_cast di un puntatore o riferimento) provoca il comportamento non definito.

struct C
{
        C();
        ~C();
};

int main()
{
        const C* const p = new const C;

        C* const q = const_cast<C*>(p); // OK, but writes through q cause UB

        // ...

        delete p; // valid, it doesn't matter that p and *p are const

        return 0;
}

Altri suggerimenti

Nel tuo esempio mucchio, new restituisce un puntatore non-const. Il fatto che hai memorizzato in un puntatore a const (e poi const_casted di nuovo a un puntatore a non-const) non cambia il fatto che l'oggetto in sé non è const nello stesso modo come una pila-assegnati è.

Tuttavia, è possono creare un oggetto const sul mucchio:

const Class* object = new const Class();

In tal caso, la fusione ad un puntatore non-const e chiamando un metodo non const sarebbe la stessa situazione come oggetto stack allocato const.

(L'idea di creare un oggetto const sul mucchio era nuovo per me, non avevo mai visto prima. Grazie a Charles Bailey.)

Sì, un oggetto heap allocata può essere const. Considerate questo estratto dall'esempio in 7.1.5.1/5:

const int* ciq = new const int (3);    // initialized as required
int* iq = const_cast<int*>(ciq);       // cast required
*iq = 4;                               // undefined: modifies a const object

L'esempio che ha dato in questione è bene perché non state chiedendo new per rendere un oggetto const; sei solo memorizzare il risultato in un const puntatore a.

Non dimenticare mutevoli membri

Non sarà comportamento undefinied se l'NonConstMethod modifica solo membri qualificati mutable (vedi 7.1.5.1 (4)) di una classe qualificato const. Sì, altrimenti è un comportamento indefinito.

const A* p = new(const A);
A *q = const_cast<A*>(p);
q->NonConstMethodThatModifiesMembers();             // undefined behaviour!
q->NonConstMethodThatOnlyModifiesMutableMembers();  // defined behaviour!

Ovviamente:

struct Foo {
  const int Bar;
  Foo() : Bar(42) { }
};

Foo* foo = new Foo;
const_cast<int&>(foo->Bar); // don't do this.

const_cast può causare UB quando l'oggetto è in realtà di sola lettura (ad esempio, il compilatore può creare tali oggetti quando si utilizza stringhe hard coded nel codice, mettendoli in alcune aree di memoria che vengono letti solo) per qualche motivo . Questo non accadrà con gli oggetti heap allocata, non importa come si mantiene il loro riferimento (puntatore const, const riferimento, a prescindere).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top