«как будто» в языковых стандартах - PullRequest
13 голосов
/ 21 февраля 2010

Каково точное значение фразы «как будто» в стандарте и как она работает, когда пользователь может изменять отдельные части поведения.

Вопрос касается стандарта C ++, когда речь идет о версии nothrow operator new. 18.4.1.1/7 читает (мой акцент):

Эта версия оператора newhrow возвращает указатель, полученный , как если бы получен из обычной версии.

Насколько я понимаю, «как будто» не требует конкретной реализации, пока поведение является соответствующим. Поэтому, если operator new был реализован следующим образом (я знаю, что это не совместимая реализация, поскольку нет цикла или использования new_handler; но я сокращаю это, чтобы сосредоточиться на моей проблеме):

// NOTE - not fully compliant - for illustration purposes only.
void *operator new(std::size_t s)
{
    void *p = malloc(s);
    if (p == 0)
        throw std::bad_alloc();
    return p;
}

Тогда было бы законно написать версию nothrow, как это:

// NOTE - not fully compliant - for illustration purposes only.
void *operator new(std::size_t s, const std::nothrow_t &nt)
{
    return malloc(s);
}

Но, скажем, программа заменяет operator new на другой распределитель. Означает ли "как будто", что компилятор должен автоматически изменить поведение версии nothrow, чтобы использовать этот другой распределитель? Обязан ли разработчик заменять как обычную, так и нетковую версии?

Ответы [ 3 ]

7 голосов
/ 21 февраля 2010

От 1,9 "Выполнение программы:

соответствующие реализации требуются для эмуляции (только) наблюдаемого поведения абстрактной машины

и в информационной сноске:

Это положение иногда называют правилом «как будто», потому что реализация может свободно игнорировать любое требование этого международного стандарта, если в результате это требование будет выполнено, насколько это можно определить из наблюдаемое поведение программы. Например, фактическая реализация не должна оценивать часть выражения, если она может сделать вывод, что ее значение не используется и что не возникает никаких побочных эффектов, влияющих на наблюдаемое поведение программы.

Стандарт особо отмечает, что требование "как-будто" является обязательным для замещающей версии nothrow версии operator new(). Тем не менее, как я читал, это требование попадет на программиста, переопределяющего operator new(), а не на компилятор. Обратная сторона этой ответственности заключается в том, что я думаю, что стандарт в значительной степени требует, чтобы стандартная реализация nothrow operator new(), предоставляемого библиотекой, должна была что-то делать по аналогии с вызовом throwing new в try / catch и возвращать 0, если std::bad_alloc пойман.

Где «как будто правило» могло бы проявиться здесь, если бы компилятор / компоновщик / все, что было достаточно умным, чтобы выяснить, что при использовании броска по умолчанию new(), не бросание по умолчанию new() может использовать ярлык, но если бросок по умолчанию new() был переопределен, небросок по умолчанию new() должен был бы действовать иначе. Я уверен, что это технически возможно для реализации (даже если вы, вероятно, не можете выразить это в стандартном C ++). Я был бы удивлен, если бы была когда-либо реализация, которая сделала бы это.

Возможно, я слишком много читаю в требовании, но я думаю, что это можно сделать вывод.

2 голосов
/ 21 февраля 2010

Если изменение в распределителе в operator new вносит заметные изменения в поведение совместимой программы на C ++, тогда да, это может потребовать изменения в реализации версии no-throw . В частности, если operator delete ожидает только блоки, выделенные новым распределителем, то no-throw new должен измениться.

Мое чтение таково, что использование , как если бы , позволяет реализацию, подобную вашей, когда пользователь не переопределил стандарт operator new. Как только он это сделает, реализация не должна использовать based *1013* no-throw operator new на основе malloc и должна либо явно вызывать объявленную пользователем версию, либо, по крайней мере, повторно использовать объявленную пользователем версию, достаточную для соответствующая программа не может сказать, что это не то, как была реализована версия no-throw .

0 голосов
/ 21 февраля 2010

Разработчик должен заменить как обычную, так и ненковую версии. Проверьте эту статью на GOTW.

Я предполагаю, что стандарт устанавливает требования к реализациям по умолчанию компилятора (и среды выполнения). Таким образом, «как будто», которое вы цитируете, предназначено для информирования поставщика компилятора о том, что его реализации этих методов по умолчанию должны соответствовать указанным критериям. Если разработчик решает переопределить только одну версию оператора new, я не думаю, что ответственность за то, чтобы все остальные версии оператора были совместимы с новой версией, лежит на компиляторе. Это ответственность разработчика. Но это все мое мнение, в данный момент у меня нет под рукой спецификации, чтобы увидеть, что там написано.

...