Выделенный "куче" может возразить быть константой в C++?

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

const Class object;

после того, как та попытка назвать метод неконстанты на таком объекте является неопределенным поведением:

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

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

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

также неопределенное поведение?

19
задан Kevin Panko 19 December 2009 в 01:42
поделиться

6 ответов

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

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;
}
19
ответ дан 30 November 2019 в 03:48
поделиться

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

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

const Class* object = new const Class();

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

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

11
ответ дан 30 November 2019 в 03:48
поделиться

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

2
ответ дан 30 November 2019 в 03:48
поделиться

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

Неопределенное поведение не будет, если NonConstMethod изменяет только изменяемые квалифицированные члены (см. 7.1. 5.1 (4)) квалифицированного класса const. Да, в противном случае это поведение undefined.

const A* p = new(const A);
A *q = const_cast<A*>(p);
q->NonConstMethodThatModifiesMembers();             // undefined behaviour!
q->NonConstMethodThatOnlyModifiesMutableMembers();  // defined behaviour!
1
ответ дан 30 November 2019 в 03:48
поделиться

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

0
ответ дан 30 November 2019 в 03:48
поделиться

Очевидно:

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

Foo* foo = new Foo;
const_cast<int&>(foo->Bar); // don't do this.
1
ответ дан 30 November 2019 в 03:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: