Подтвердить что ты не робот

Может ли объект, выделенный для кучи, быть const в С++?

В С++ объект, выделенный для стека, может быть объявлен const:

const Class object;

после этого попытка вызова неконстантного метода для такого объекта - это поведение undefined:

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

Может ли выделенный объект с кучей const с теми же последствиями? Я имею в виду, возможно ли следующее:

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

также является undefined поведением?

4b9b3361

Ответ 1

Да. Это законно для создания и уничтожения объекта кучи const. Как и в случае с другими объектами const, результаты управления им как объектом не const (например, через const_cast указателя или ссылки) приводят к поведению undefined.

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;
}

Ответ 2

В примере с кучей new возвращает указатель на неконстантный. Тот факт, что вы сохранили его в указателе на const (а затем const_cast отредактировал его обратно на указатель на неконстантный), не изменяет того факта, что сам объект не является константой так же, как стек -ограниченный.

Однако вы можете создать объект const в куче:

const Class* object = new const Class();

В таком случае приведение к указателю на не-const и вызов неконстантного метода будет той же самой ситуацией, что и объект, связанный со стеком const.

(Идея создания объекта const в куче была для меня новой, я никогда не видел этого раньше. Спасибо Чарльзу Бейли.)

Ответ 3

Да, объект, выделенный для кучи, может быть const. Рассмотрим этот отрывок из примера в 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

Пример, который вы задали в вопросе, прекрасен, потому что вы не просите new создать объект const; вы просто сохраняете результат в указателе на константу.

Ответ 4

Очевидно:

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

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

Ответ 5

Не забывайте изменяемые члены

Это не будет неопределенным поведением, если NonConstMethod только модифицирует mutable квалифицированных членов (см. 7.1.5.1 (4)) класса с константой. Да, в противном случае это поведение undefined.

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

Ответ 6

const_cast может вызвать UB, когда объект действительно доступен только для чтения (например, компилятор может создавать такие объекты, когда вы используете жестко закодированные строки в своем коде, помещая их в определенные области памяти, которые только читаются) по какой-либо причине, Это не будет происходить с выделенными кучами объектами, независимо от того, как вы храните их ссылку (указатель const, const reference, что угодно).