Partage
  • Partager sur Facebook
  • Partager sur Twitter

valeur par défaut pour argument de type const ref?

    19 mars 2025 à 22:47:57

    Salut tout le monde !

    Je me demande s'il est possible de définir une valeur par défaut pour un argument de type const reference dans une fonction en C++. J'ai écrit le code suivant, qui compile sans problème et passe clang-tidy sans erreurs. Cependant, je suis un peu perplexe car je n'ai jamais vu cette pratique auparavant. Est-ce une bonne pratique ? Y a-t-il des inconvénients ou des alternatives recommandées ?

    Exemple :

    main.cpp

    #include "Character.h"
    
    #include <iostream>
    
    
    void callPrintName(const Character& character = Character("unknown")) {
      character.printName();
    }
    
    
    int main() {
      Character c("Jak");
      callPrintName(c);
      callPrintName();
    
      return 0;
    }

    Character.h

    #pragma once
    
    #include <string>
    
    
    class Character {
     public:
      Character(const std::string& name);
      void printName() const;
    
     private:
      std::string name_;
    };
    

    Character.cpp

    #include "Character.h"
    
    #include <iostream>
    
    
    Character::Character(const std::string& name) : name_(name) {}
    
    void Character::printName() const {
      std::cout << "Name : " << name_ << std::endl;
    }


    Merci d'avance !

    PS : Je me pose ce genre de question tordue car je travaille sur un projet où un ancien développeur s'est amusé à mettre plein de fonctions qui passent leurs arguments par valeur mais contiennent aussi des arguments par défaut. Du coup j'aimerais ajouter un passage par référence constante pour améliorer la qualité du code sans casser l'idée de l'argument par défaut qui avait été ajouté.

    -
    Edité par ThomasAirain 19 mars 2025 à 23:42:25

    • Partager sur Facebook
    • Partager sur Twitter
      19 mars 2025 à 23:04:35

      Oui.

      Hors sujet, ajouter des references n'est pas forcement une amélioration. Dans ton dernier code par exemple, il vaudrait mieux ajouter un std::move sur name.

      Utilise clang-tidy et les warnings "modernize" pour analyser ton code.

      • Partager sur Facebook
      • Partager sur Twitter
        19 mars 2025 à 23:24:28

        D'ac merci ;) par contre une référence constante me paraît plus logique qu'une rvalue pour le constructeur de la classe Character. Si tu définies ceci :

        Character::Character(std::string&& name) : name_(name) {}


        tu forces le développeur à utiliser std::move() s'il veut passer une variable en argument du constructeur, ce qui l'empêchera d'utiliser sa variable dans les lignes du dessous.

        -
        Edité par ThomasAirain 19 mars 2025 à 23:49:52

        • Partager sur Facebook
        • Partager sur Twitter
          20 mars 2025 à 23:39:59

          Ou alors tu peux aussi définir 2 destructeurs mais ça fait peut-être usine à gaz
          • Partager sur Facebook
          • Partager sur Twitter
            21 mars 2025 à 2:05:36

            Utiliser std::move ne veut pas forcément dire avoir un rvalue en paramètre.

            Character::Character(std::string name) : name_(std::move(name)) {}

            On ne force pas à avoir une rvalue et la mémoire n'est pas copiée, mais bien déplacée dans le membre. Comme dit @gbdivers, ce sont des warnings que remonte clang-tidy.

            Dans les faits, avoir un constructeur avec une rvalue et un autre avec const-réf permet d'avoir un code optimal, mais c'est lourd et le nombre de constructeur est exponentiel au nombre de paramètre pour un bénéfice discutable. Du coup, si le paramètre implémente un constructeur de déplacement, il vaut mieux le prendre par valeur et faire un std::move sur l'init du membre. Sur l'appel, si l'utilisateur passe une référence, il n'y a pas de changement, mais s'il donne une rvalue/temporaire il n'y aura qu'une allocation de std::string (plutôt que 2 avec une référence).

            De plus, si le type est petit (on va dire plus petit oui égal à 2 * sizeof(void*)), il vaut mieux prendre par valeur plutôt qu'une référence, car le passage de paramètre est plus efficace. C'est pour cela qu'il est conseillé de prendre par valeur les vues comme std::string, std::span, QStringView, etc.

            -
            Edité par jo_link_noir 21 mars 2025 à 2:06:03

            • Partager sur Facebook
            • Partager sur Twitter

            valeur par défaut pour argument de type const ref?

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            • Editeur
            • Markdown