Массив объектов, которые не удаляются [дубликат]

>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
3
задан Alok Save 23 December 2012 в 18:11
поделиться

4 ответа

Итак, почему стандартный мандат, вызывающий не виртуальную функцию-член через удаленный указатель, является неопределенным поведением, когда на самом деле он может с уверенностью сказать, что разыменование этого должно быть выражением, которое должно вызывать неопределенное поведение?

[expr.ref] в абзаце 2 говорит, что вызов функции-члена, такой как ptr->doSomething(), эквивалентен (*ptr).doSomething(), поэтому вызов нестатической функции-члена является разыменованием. Если указатель недействителен, это неопределенное поведение.

Независимо от того, нужен ли сгенерированный код для разыменования указателя для конкретных случаев, абстрактная машина, которую модели компилятора делает , делает принципиальный разыгрыш.

Усложнение языка для определения того, какие именно случаи будут разрешены, если они не имеют доступа к каким-либо членам, будет иметь почти нулевую выгоду. В случае, когда вы не можете увидеть определение функции, о котором вы не знаете, если вызов будет безопасным, потому что вы не можете знать, использует ли функция this или нет.

Просто не делайте этого делайте это, нет веских оснований, и это хорошая вещь, которую язык запрещает.

5
ответ дан Jonathan Wakely 26 August 2018 в 16:20
поделиться

В языке C ++ (согласно C ++ 03) в самой попытке использовать значение недопустимого указателя вызывает неопределенное поведение. Нет необходимости разыгрывать его для UB. Достаточно просто прочитать значение указателя. Концепция «недопустимое значение», вызывающая UB, когда вы просто пытаетесь прочитать это значение, фактически распространяется почти на все скалярные типы, а не только на указатели.

После delete указатель обычно недействителен в этом конкретном смысл, т. е. чтение указателя, который якобы указывает на то, что только что было «удалено», приводит к неопределенному поведению.

int *p = new int();
delete p;
int *p1 = p; // <- undefined behavior

Вызов функции-члена с помощью недопустимого указателя - это только конкретный случай выше. Указатель используется как аргумент для неявного параметра this. Передача указателя является аргументом без ссылки - это акт его чтения, поэтому поведение в вашем примере не определено.

Итак, ваш вопрос действительно сводится к тому, почему чтение недопустимых значений указателя вызывает неопределенное поведение ,

Ну, может быть много причин для конкретной платформы. Например, на некоторых платформах акт чтения указателя может привести к тому, что значение указателя будет загружено в определенный выделенный адресный регистр. Если указатель недействителен, оборудование / ОС может немедленно обнаружить его и вызвать ошибку программы. Фактически, так работает наша популярная платформа x86 в отношении сегментных регистров. Единственная причина, по которой мы ничего не слышим, это то, что популярные ОС придерживаются модели с плоской памятью, которая просто не активно использует регистры сегментов.


C ++ 11 фактически утверждает, что dereferencing недопустимые значения указателя вызывает поведение undefined , в то время как все другие недопустимые значения указателя вызывают поведение, определенное реализацией . Он также отмечает, что поведение, определяемое реализацией в случае «копирования недопустимого указателя», может привести к «системному сбою во время выполнения». Таким образом, на самом деле можно было бы тщательно маневрировать через лабиринт спецификации C ++ 11 и успешно прийти к выводу, что вызов не виртуального метода с помощью недопустимого указателя должен привести к реализации поведение, упомянутое выше. В любом случае всегда будет существовать «системная ошибка выполнения».

5
ответ дан AnT 26 August 2018 в 16:20
поделиться

Выделение this в этом случае является эффектом детализации реализации. Я не говорю, что указатель this не определен стандартом, поскольку он есть, но из семантически абстрагированной точки зрения, что является целью разрешить использование уничтоженных объектов только потому, что есть угловой случай в котором на практике это будет «безопасно»? Никто. Так это не так. Объект не существует, поэтому вы не можете вызывать функцию на нем.

2
ответ дан Lightness Races in Orbit 26 August 2018 в 16:20
поделиться

Потому что количество случаев, в которых оно может быть надежным, настолько тонкое, что делает его все еще необоснованной глупой идеей. Нет смысла определять поведение.

9
ответ дан Puppy 26 August 2018 в 16:20
поделиться
Другие вопросы по тегам:

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