Для примитивных типов просто возвращайте по значению. Нет причины возвращать примитив по константной ссылке.
Для не примитивных типов это зависит.
Если возвращаемое значение является локальной переменной функции, то вы должны возвращать значение. В противном случае переменная будет уничтожена до того, как вызывающая сторона сможет использовать возвращенную ссылку.
Если возвращаемое значение является членом класса, у вас есть выбор.
Возврат по константной ссылке позволяет избежать копий, что может быть преимуществом в производительности. Однако он связывает ваш интерфейс с реализацией, то есть член данных и возвращаемое значение должны быть одного типа. Это также менее безопасно, потому что вызывающая сторона может сохранять ссылку дольше, чем время жизни объекта, например:
const X& x = y->foo();
delete y;
// use x, oops!
Возврат по значению включает одну или две копии, в зависимости от того, можете ли вы воспользоваться преимуществами оптимизации возвращаемого значения (что, вероятно, для простых методов get (), таких как этот). Кроме того, копии объектов, использующие конструкторы копирования по умолчанию, могут копироваться более эффективно (подумайте: компилятор может просто запоминать данные).
Рекомендация: начните с возврата по значению и переключитесь на возврат по константной ссылке только после определения того, что этот вызов / копия, как известно, является проблемой производительности.
Наконец, другой альтернативой является возврат по параметру, который может быть полезен для более сложных объектов (например, строки):
void foo(X& return_val) { return_val = member_variable_; }
или
void foo(X* return_val) {
assert(return_val != 0);
*return_val = member_variable_;
}