Le programme court suivant
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
a un problème de référence pendant, qu'aucun compilateur ne semble avertir. Le problème est que les temporaires peuvent être liés à des const-refs, que vous pouvez ensuite conserver. La question est alors: Existe-t-il une méthode pour éviter d'entrer dans ce problème? De préférence, qui n'implique pas de sacrifier l'exactitude de const, ou de toujours faire des copies de gros objets.
std::unique_ptr
pour la propriété exclusive, soit pour la propriétéstd::shared_ptr
partagée, soitstd::weak_ptr
, au moins, pour reconnaître les données perdues).-fsanitize=address
. Je ne pense pas qu'il existe de meilleure pratique pour l'éviter sans sacrifier les performances.Réponses:
Dans le cas où une méthode conserve une référence après son retour, c'est une bonne idée d'utiliser à la
std::reference_wrapper
place de la référence normale:Woop (std::vector<int> const &&) = delete;
pour votre méthode:la source
Une façon de rendre votre classe moins vulnérable pourrait être d'ajouter un constructeur supprimé qui prend une référence à droite. Cela empêcherait votre instance de classe de créer des liaisons avec des temporaires.
Ce constructeur supprimé ferait en fait le code O / P ne pas compiler, ce qui peut être le comportement que vous recherchez?
la source
Je suis d'accord avec les autres réponses et commentaires que vous devriez réfléchir attentivement si vous avez vraiment besoin de stocker une référence dans la classe. Et que si vous le faites, vous voudrez probablement un pointeur non-const vers un vecteur const à la place (ie
std::vector<int> const * numbers_
).Cependant, si c'est le cas, je trouve que les autres réponses actuellement affichées sont à côté du sujet. Ils vous montrent tous comment vous approprier
Woop
ces valeurs.Si vous pouvez vous assurer que le vecteur que vous transmettez survivra à votre
Woop
instance, vous pouvez explicitement désactiver la construction d'un àWoop
partir d'une valeur r. C'est possible en utilisant cette syntaxe C ++ 11:Maintenant, votre exemple de code ne se compilera plus. Le compilateur avec donne une erreur similaire à:
PS: Vous voulez probablement un constructeur explicite, voir par exemple Que signifie le mot-clé explicite? .
la source
Pour éviter ce cas particulier, vous pouvez choisir de prendre un pointeur (car ce
Weep(&std::vector<int>{1,2,3})
n'est pas autorisé) ou vous pouvez prendre une référence non const qui provoquera également une erreur sur un temporaire.Celles-ci ne garantissent toujours pas que la valeur reste valide, mais empêche au moins l'erreur la plus simple, ne crée pas de copie et n'a pas besoin d'
nums
être créée d'une manière spéciale (par exemple, commestd::shared_ptr
ou lestd::weak_ptr
fait).std::scoped_lock
prendre une référence au mutex serait un exemple, et celui où un ptr unique / partagé / faible n'est pas vraiment souhaité. Souvent, lestd::mutex
sera simplement un membre de base ou une variable locale. Vous devez toujours être très prudent, mais dans ces cas, il est généralement facile de déterminer la durée de vie.std::weak_ptr
est une autre option pour les non-propriétaires, mais vous forcez ensuite l'appelant à utilisershared_ptr
(et donc également à allouer des tas), et parfois ce n'est pas souhaité.Si une copie est OK, cela évite simplement le problème.
Si
Woop
doit s'approprier, passez comme valeur r et déplacez (et évitez complètement les problèmes de pointeur / référence), ou utilisezunique_ptr
si vous ne pouvez pas déplacer la valeur elle-même ou si le pointeur reste valide.Ou si la propriété est partagée, vous pouvez l'utiliser
shared_ptr
pour tout, et elle sera supprimée avec la référence finale, mais cela peut rendre la surveillance des cycles de vie des objets très déroutante si elle est sur-utilisée.la source
Vous pouvez utiliser
template programming
etarrays
si vous voulez avoir un objet qui contient unconst
conteneur. En raison duconstexpr
constructeur etconstexpr arrays
vous réalisezconst correctness
etcompile time execution
.Voici un article qui peut être intéressant: std :: move a const vector
exécuter du code
Production:
la source
std::array
ceci est garanti de copier, même si un mouvement serait autrement disponible. En plus de celawooping1
etwooping2
ne sont pas du même type, ce qui est loin d'être idéal.