Каковы варианты использования функции возврата по константному значению для не встроенного типа? - PullRequest
37 голосов
/ 10 июня 2011

Недавно я прочитал, что при возврате по значению из функции имеет смысл квалифицировать возвращаемый тип const для не встроенных типов, например ::10000

const Result operation() {
    //..do something..
    return Result(..);
}

Я изо всех сил пытаюсь понять преимущества этого, после того, как объект был возвращен, конечно, это выбор вызывающего абонента, чтобы решить, должен ли возвращаемый объект быть const?

Ответы [ 3 ]

34 голосов
/ 10 июня 2011

По сути, здесь есть небольшая языковая проблема.

std::string func() {
    return "hai";
}

func().push_back('c'); // Perfectly valid, yet non-sensical

Возвращение константных значений является попыткой предотвратить такое поведение.Однако в действительности это приносит больше вреда, чем пользы, потому что теперь, когда здесь есть ссылки на rvalue, вы просто предотвратите семантику перемещения, которая отстой, и вышеупомянутое поведение, вероятно, будет предотвращено разумным использованием rvalue и lvalue*this перегрузка.Кроме того, вам все равно придется быть немного идиотом, чтобы сделать это.

12 голосов
/ 10 июня 2011

Это иногда полезно.Смотрите этот пример:

class I
{
public:
    I(int i)                   : value(i) {}
    void set(int i)            { value = i; }
    I operator+(const I& rhs)  { return I(value + rhs.value); }
    I& operator=(const I& rhs) { value = rhs.value; return *this; }

private:
    int value;
};

int main()
{
    I a(2), b(3);
    (a + b) = 2; // ???
    return 0;
}

Обратите внимание, что значение, возвращаемое operator+, обычно считается временным.Но это явно модифицируется.Это не совсем желательно.

Если вы объявите тип возврата operator+ как const I, компиляция не удастся выполнить.

9 голосов
/ 10 июня 2011

Нет возврата при возврате по значению.Это не имеет смысла.

Единственное отличие состоит в том, что он не позволяет людям использовать его как lvalue:

class Foo
{
    void bar();
};

const Foo foo();

int main()
{
    foo().bar(); // Invalid
}
...