Ответ 1
Является ли оно допустимым для метки
Wrapper::get()
как функции членаpure
? Это зависит только от неявного экземпляраWrapper
, но эти данные могут измениться.
Да, Wrapper::get()
соответствует требованиям атрибута gcc pure
. Обратите внимание, однако, что __attribute__((pure))
не означает чистое в академическом смысле, то есть обладает свойством ссылочной прозрачности. Последнее может быть передано через более строгий __attribute__((const))
:
__attribute__((const))
Многие функции не проверяют значения, кроме их аргументов, и не имеют эффектов, кроме возвращаемого значения. В основном это просто чуть более строгий класс, чем атрибут
pure
ниже, поскольку функция не может читать глобальную память.Обратите внимание, что функция, имеющая аргументы указателя и анализирующая данные указываемый не должен быть объявлен
const
. Аналогично, функция, которая вызывает функция неconst
обычно не должна бытьconst
. Это не имеет смысла для функцииconst
для возвратаvoid
.
Но так как Wrapper::get()
не обладает свойством ссылочной прозрачности, подразумеваемым __attribute__((const))
, он не может быть помечен как таковой.
ИЗМЕНИТЬ
Гарантия на pure
-ness (в смысле gcc) функции может использоваться для оптимизации только блока кода, который не содержит записи в глобальную память (и, в частности, не перемежается вызовами к функциям не pure
). Примеры:
struct Wrapper {
int i;
int get() const __attribute__((pure)) { return i; }
void set(int x) { i = x; }
};
long foo(Wrapper* w)
{
// w->get() can be computed once
return 2 * w->get() * w->get();
}
long bar(Wrapper* w)
{
// w->get() can be computed once (even though below code writes to memory,
// that memory is freshly allocated and cannot be accessed by w->get())
long result = 2;
result *= w->get();
result *= w->get();
return result;
}
long baz(Wrapper* w)
{
// both w->get()s must be evaluated, since non-pure code occurs between them
long result = 2;
result *= w->get();
std::cout << "Result after the first muliplication: " << result << std::endl;
result *= w->get();
return result;
}