Постоянное значение функции для возвращаемого типа данных
Каково реальное значение const для 2-го объявления foo:B()?
int foo::A() const {
return m_var;
}
int const foo::B() {
return m_var;
}
Для 1-го объявления я точно знаю, что оно "защищает" переменную-член, т.е. m_var.
Но в чем весь смысл 2-го объявления о том, что оно просто возвращает константу int вызывающей стороне, вероятно, непостоянную переменную? Я имею в виду, имеет ли это смысл по какой-либо причине?
1 ответ
Случай 1: const
после подписи функции говорит, что функция не изменит объект. Таким образом, вы можете использовать его на const
объекты (или с указателем на const
или const
ссылка).
Случай 2: const
перед именем функции действительно о типе возвращаемого значения. Вы совершенно правы: на практике это ничего не меняет для объекта, так как возвращение в этом фрагменте выполняется по значению, а это значение во временном интервале, которое нельзя изменить (например, ++
или --
не будет действительным в любом случае, потому что нет lvalue).
Случай 3: const в возвращаемом типе имеет больше смысла с возвратом указателя на const или ссылки на const. В этом случае это предотвратит изменение состояния объекта извне.
Вот краткое изложение:
class foo {
public:
int A() const { // const function
return m_var;
}
int const B() { // non const function, but const return type
return m_var;
}
int const& C() const { // non const function, but const reference return type
return m_var;
}
private:
int m_var;
};
int main() {
const foo x{};
x.A(); // ok
//x.B(); // not ok -> function B() doesn't guarantee to leave x unchanged.
x.C(); // ok
const int& y = x.C(); // ok (y will not alter m_var.
//int& z = x.C(); // not ok since z is not const
return 0;
}
Случай 4: (спасибо HolyBlackCat за указание на это). То, что не имеет значения для скаляров в случае 2, может иметь смысл для классов. предполагать m_var
будет класса bar
:
class bar {
public:
void change_it() {}
void read_it() const {}
};
Тогда возвращаемое значение const будет иметь значение:
foo u{};
u.B(); // ok
u.B().read_it(); // ok
u.B().change_it(); // not ok because of constness of B().