Могут ли быть разные неявные объекты, основанные на более позднем решении времени выполнения в C ++ 20? - PullRequest
11 голосов
/ 11 марта 2020

Этот вопрос относится к добавлению P0593 к последней версии C ++ 20 .

Вот мой пример:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}

Правильно ли определен этот код для всех входных данных по последнему черновику?

Обоснование, выраженное в P0593, довольно ясно показывает, что раскомментирование [2] приведет к неопределенному поведению из-за строгого нарушения псевдонимов, если два элементы ввода пользователя отличаются. Предполагается, что создание неявного объекта происходит только один раз, в точке malloc; он не запускается оператором присваивания в foo.

. Для любого фактического запуска программы существует член неопределенного набора неявных объектов, который делает программу хорошо определенной. Но мне не ясно, нужно ли делать выбор неявного создания объекта, упомянутого в [intro.object] / 10, когда происходит malloc; или может ли решение «путешествовать во времени».

Та же проблема может возникнуть для программы, которая считывает двоичный двоичный объект в буфер, а затем принимает решение во время выполнения о том, как получить к нему доступ (например, десериализация и заголовок). говорит нам, подходит ли float или int).

1 Ответ

9 голосов
/ 11 марта 2020

Предполагается, что создание неявного объекта происходит только один раз, в точке malloc; оно не вызывается оператором присваивания в foo.

Это не имеет значения. Важно то, какой объект создается. Стандарт гласит, что создаваемый объект - это объект, который превращает что-то, что было бы в UB, в четко определенный код:

, что операция неявно создает и запускает время жизни нуля или более объектов неявного типы времени жизни ([basi c .types]) в указанном регионе хранения, если это приведет к определенному поведению программы.

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

Таким образом, местоположение создания всегда является «операцией», но определение того, что создается, основано на том, как память используется во время выполнения (ie: поведение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...