Пометка функции как не имеющей побочных эффектов в Visual Stack Overflow

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

// 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) показывает, что компилятор действительно генерирует два вызова. Это даже делает, если я помещаю обе функции в один модуль.

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

2

Решение

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

0

Другие решения

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

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

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

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

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

Например:

// 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 не было никаких побочных эффектов.

0

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

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

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

-1
По вопросам рекламы [email protected]