web-dev-qa-db-fra.com

But de retourner par valeur const?

Quel est le but du const dans cela?

const Object myFunc(){
    return myObject;
}

Je viens tout juste de commencer à lire Effective C++ et l’article 3 le préconisent. Une recherche Google recueille des suggestions similaires, mais aussi des contre-exemples. Je ne vois pas comment utiliser const ici serait préférable. En supposant qu'un retour par valeur est souhaitable, je ne vois aucune raison de protéger la valeur renvoyée. L'exemple donné pour expliquer pourquoi cela pourrait être utile est d'empêcher les conversions booléennes non intentionnelles de la valeur de retour. Le problème réel est alors que les conversions booléennes implicites devraient être empêchées avec le mot clé explicite.

L'utilisation de const empêche l'utilisation d'objets temporaires sans affectation. Donc, je ne pouvais pas effectuer d'expressions arithmétiques avec ces objets. Il ne semble pas qu'il y ait jamais eu de cas où un const non nommé est utile.

Que gagne-t-on en utilisant const ici et quand serait-il préférable?

EDIT: remplacez l’exemple arithmétique par n’importe quelle fonction qui modifie un objet que vous voudrez peut-être exécuter avant une affectation.

111
Praxeolitic

Dans l'hypothèse où vous pourriez effectuer une opération potentiellement non coûteuse sur un objet, le renvoi par valeur const vous évite d'appeler accidentellement cette opération sur une base temporaire. Imagine ça + a renvoyé une valeur non-const, et vous pourriez écrire:

(a + b).expensive();

Cependant, à l’âge de C++ 11, il est vivement recommandé de renvoyer des valeurs non constantes afin de tirer pleinement parti des références à la valeur rvalue, qui n’ont de sens que sur des valeurs non constantes.

En résumé, il y a une justification de cette pratique, mais elle est essentiellement obsolète.

115
Kerrek SB

C'est joliinutile pour renvoyer une valeur const à partir d'une fonction.

C’est difficile de l’obtenir pour qu’il ait un effet sur votre code:

const int foo() {
   return 3;
}

int main() {
   int x = foo();  // copies happily
   x = 4;
}

et :

const int foo() {
   return 3;
}

int main() {
   foo() = 4;  // not valid anyway for built-in types
}

// error: lvalue required as left operand of assignment

Bien que vous pouvez remarquer si le type de retour est un type défini par l'utilisateur :

struct T {};

const T foo() {
   return T();
}

int main() {
   foo() = T();
}

// error: passing ‘const T’ as ‘this’ argument of ‘T& T::operator=(const T&)’ discards qualifiers

il est douteux que cela profite à quiconque.

Renvoyer une référence est différent, mais à moins que Object ne soit un paramètre de modèle, vous ne le faites pas.

39

Il s'assure que l'objet retourné (qui est une RValue à ce point) ne peut pas être modifié. Cela fait en sorte que l'utilisateur ne puisse pas penser comme ceci:

myFunc() = Object(...);

Cela fonctionnerait bien si myFunc retournait par référence, mais est certainement un bogue quand retourné par valeur (et ne sera probablement pas attrapé par le compilateur). Bien sûr, dans C++ 11 avec ses valeurs, cette convention n'a pas plus de sens que précédemment, puisqu'un objet const ne peut pas être déplacé, donc cela peut avoir des effets assez lourds sur les performances.

5
Grizzly