Чи можуть існувати різні неявні об'єкти, засновані на більш пізньому рішенні виконання у C ++ 20?


11

Це питання стосується доповнення 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відбувається; чи рішення може «подорожувати часом».

Це ж питання може виникнути і для програми, яка читає двійкову крапку в буфер і потім приймає рішення про час доступу до неї (наприклад, дезаріалізація; а заголовок повідомляє, чи з’являється флоат або int).

Відповіді:


9

Створення неявного об'єкта, як передбачається, відбудеться лише один раз, у точці malloc; його не спрацьовує оператор призначення в foo.

Це не актуально. Важливо те, який об’єкт створюється. Стандарт говорить, що створений об'єкт - це той, який робить щось, що було б UB, у чітко визначений код:

ця операція неявно створює і запускає час життя нульових або більше об'єктів типів неявного періоду життя ([basic.types]) у визначеній області зберігання, якщо це буде призводити до того, що програма має певну поведінку.

Поведінка в кінцевому рахунку заснована на виконанні часу виконання, а не на статичному аналізі. Тож вам потрібно лише стежити за виконанням програми до тих пір, поки ви не зіткнетесь із випадком, коли поведінку не було б визначено, але все-таки було б визначено, якби об’єкт певного типу був створений у цьому сховищі на момент проведення відповідної операції.

Отже, місце створення завжди є "операцією", але визначення того, що створюється, базується на тому, як пам'ять звикає під час виконання (тобто: поведінку).


2
Щоб було зрозуміло, ви говорите, що мій код чітко визначений?
ММ

2
@MM: Це правильно.
Нікол Болас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.