Пометка функции как не имеющей побочных эффектов с помощью Visual C++

Рассмотрим следующий (немного продуманный) пример:

// a.cpp
int mystrlen(const char* a) {
   int l = 0;
   while (a[l]) ++l;
   return l;
}

// b.cpp
extern int mystrlen(const char*);
int foo(const char* text) {
   return mystrlen(text) + mystrlen(text);
}

Было бы очень хорошо иметь возможность сообщить компилятору, что mystrlen() не имеет побочных эффектов и, таким образом, он может повторно использовать старый результат из mystrlen(text) вместо того, чтобы вызывать его дважды.

Я ничего не нашел в документах об этом, и restrict или одна из его вариаций, похоже, тоже не работают. Взгляд на код вывода со всеми включенными оптимизациями (переключатель /Ox) показывает, что компилятор действительно генерирует два вызова. Это происходит даже в том случае, если я помещаю обе функции в один модуль.

Любое решение для этого или кто-нибудь может подтвердить, что в VС++ нет решения?


person cxxl    schedule 16.09.2013    source источник
comment
Вам нужен более функциональный язык.   -  person SLaks    schedule 16.09.2013
comment
Это происходит (вызывается дважды), даже когда вы включаете всю оптимизацию? А что, если он находится в том же исходном файле? Все тот же результат?   -  person Floris    schedule 16.09.2013
comment
@Floris: я использовал /Ox, и даже если в одном модуле он дважды встраивает функцию.   -  person cxxl    schedule 16.09.2013
comment
stackoverflow.com/questions/16233497/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 28.06.2015
comment
возможный дубликат чистых/константных атрибутов функции в разных компиляторах   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 28.06.2015


Ответы (3)


MSVC не поддерживает атрибуты pure/const и не собирается их поддерживать. См. https://connect.microsoft.com/VisualStudio/feedback/details/804288/msvc-add-const-and-pure-like-function-attributes. Другие компиляторы, такие как GCC и Clang, поддерживают такие атрибуты. Также см. чистые/константные атрибуты функций в разных компиляторах.

person bcmpinc    schedule 07.07.2015

То, что вы ищете, не поможет вам.

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

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

Здесь вы просите компилятор поверить, что голый указатель, который у вас есть, кто знает, где будет поддерживать согласованное содержимое между двумя вызовами функций. Это много предположений. Конечно, вы не объявили свой указатель изменчивым, но все же это много предположений.

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

Например:

// b.cpp
extern int mystrlen(const char*);
int foo(int bar) {
   char number[20];
   snsprintf(number, 20, "%d", bar);
   return mystrlen(number) + mystrlen(number);
}

Учитывая предположения, которые компилятор мог бы сделать о том, что snprintf сделал с number, учитывая, что это библиотечная функция, он мог бы затем пропустить второй вызов mystrlen, если бы был способ объявить, что mystrlen не имеет побочных эффектов.

person Omnifarious    schedule 19.03.2017

Поскольку C++ — это императивный язык, а не функциональный, то, чего вы пытаетесь достичь, невозможно.

Похоже, что поведение, которое вы ожидаете здесь, - это ссылочная прозрачность, о которой нет способа сообщить компилятору в C++ (но в чисто функциональном языке программирования, таком как Haskell, это было бы неявно).

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

person Salami    schedule 04.11.2013
comment
Я не понимаю, почему императивное или функциональное имеет какое-либо отношение к возможности пометить определенную функцию как не имеющую побочных эффектов (т.е. последствий для других объектов). Без сомнения, его можно реализовать на C++. Вопрос в том, это это? - person cxxl; 29.12.2013