C++ Flux vs C-style IO?
J'ai été codage en C++ pour un petit projet passe-temps quand j'ai remarqué que je suis à l'aide de C-opérations de style pour accéder à IO (printf
, fopen
, etc.).
Est-il considéré comme "mauvaise pratique" impliquer les fonctions C dans les projets C++? Quels sont les avantages de l'utilisation des cours d'eau de style C IO accès?
Vous devez vous connecter pour publier un commentaire.
C'est un sujet brûlant.
Certaines personnes préfèrent utiliser le C++ IO, car ils sont de type sécurisé (vous ne pouvez pas avoir de divergence entre le type de l'objet et du type spécifié dans la chaîne de format), et des flux de plus naturellement avec le reste du C++ manière de coder.
Cependant, il y a aussi des arguments pour C IO fonctions (mes favoris). Certains d'entre eux sont:
printf
fonction, le code généré est plus petit (ce qui peut être important en environnement embarqué).Personnellement, je ne la considérons pas comme une mauvaise pratique à utiliser C flux dans le code C++. Certaines organisations même vous recommander pour les utiliser sur C++ flux. Ce que je considère mauvais style est à utiliser à la fois dans le même projet. La cohérence est la clé ici, je pense.
Comme d'autres l'ont noté, dans un assez gros projet, et vous ne serait probablement pas les utiliser directement, mais vous devez utiliser un ensemble de fonction wrapper (ou classes), qui conviendrait le mieux à votre norme de codage, et de vos besoins (localisation, type de sécurité, ...). Vous pouvez utiliser l'une ou l'autre interface entrée /sortie pour mettre en œuvre ce plus haut niveau de l'interface, mais vous aurez probablement utiliser un seul.
Edit: ajout de quelques informations au sujet de l'avantage de
printf
mise en forme de la fonction de la famille relatives à la localisation. Veuillez noter que ces informations ne sont valables que pour certains la mise en œuvre.Vous pouvez utiliser
%m$
au lieu de%
de paramètre de référence par l'index au lieu de référencer de manière séquentielle. Ceci peut être utilisé pour réorganiser les valeurs dans la chaîne formatée. Le programme suivant va écrireHello World!
sur la sortie standard.Envisager de traduire ce code C++:
Cela peut être vraiment difficile. Avec
printf
(et une bibliothèque commegettext
pour gérer la localisation), le code n'est pas mélangé avec de la ficelle. Nous pouvons donc passer la chaîne à l'équipe de localisation, et ne pas avoir à mettre à jour le code si il y a des cas dans certaines langues (dans certaines langues, si count de l'objet est de 0, vous utilisez une forme plurielle, dans d'autres langues, il existe trois formes de singulier, l'un quand il y a deux objets et un pluriel, ...).printf
(indice :%m$
).printf
dans toute raisonnable de source officielle que j'ai à portée de main. Où en êtes-vous de cette%2$
idée?printf
sur mon linux. Cela ne semble fonctionne sur Mac OS X si. Je ne sais pas si cela est requis par la norme.printf
et les amis sont affreusement dangereux par rapport à<iostream>
, et ne peut être prolongée, en plus de coursfopen
et amis ont aucune RAII, ce qui signifie que, à moins que vous avez prouvé avec un générateur de profils que vous avez certainement besoin de la différence de performances (que vous avez prouvé existe sur votre plate-forme et dans votre code), il faudrait être idiot pourprintf
.Edit: la Localisation est une chose intéressante que je n'avais pas considéré comme. Je n'ai jamais localisé le code et ne peut pas commenter sur la relative localizational capacité de
printf
et<iostream>
Pour un petit projet passe-temps je serais probablement aller avec le plus de type-safe C++ io ruisseaux.
Assez drôle, je n'ai jamais vu un non-trivial réel projet de vie qui utilise l'un ou l'autre. Dans tous les cas, nous avons utilisé des abstractions construit sur le système d'exploitation natif de l'API pour les IO.
Rien ne peut être considéré comme une mauvaise pratique, si elle a un but précis. Je veux dire, si IO est le goulot d'étranglement du programme, alors oui, le style C IO fonctionne plus rapidement que le C++ IO. Mais si elle ne l'est pas, j'irais avec C++ flux approche. Parce que c'est le plus mignon 🙂
Avantages
printf
les arguments sont passés par...
provoquant un comportement indéterminé si elles ne correspondent pas à la mise en forme.fclose
.Inconvénients
printf
mise en forme.À mon humble avis, un vrai programmeur C++ essaie de faire les choses dans idiomatiques C++, le C converti programmeur tente de s'accrocher sur les anciennes façons de faire les choses. Il a à voir avec de la lisibilité et de la cohérence.
Pour l'un, vous n'avez pas à convertir des objets en C++ (notamment
string
s) à C-compatible formes.str.c_str()
tout le temps...Généralement, le fichier IO code doit être encapsulé dans une classe ou d'une fonction de mise en œuvre. Je ne considère pas les choix que vous faites dans la encapsulé implémentations d'être "mauvaise pratique", je me réserve ce terme pour ce qui touche à l'utilisateur de votre bibliothèque ou d'un code (c'est à dire l'interface). Si vous êtes exposant votre e /s de fichier mécanisme dans l'interface, puis, de l'OMI, c'est une mauvaise pratique si vous utilisez IO flux ou de style C IO fonctions.
Je dirais plutôt que C-style IO fonctions sont (probablement toujours) le plus mauvais choix.
D'abord, elles s'intègrent mieux avec C++ standard des constructions telles que
std::string
. Ils s'intègrent assez bien avec STL<algorithms>
. Et ils vous permettent de créer encapsulé personnalisée en lecture/écriture opérateurs (<< et >>) de telle sorte que vos classes personnalisées ressemblent presque à des types primitifs quand il s'agit de faire des opérations d'e /s.Enfin, IO flux en C++ pouvez utiliser le mécanisme d'exception pour signaler des erreurs dans le cours d'eau ou d'opérations de lecture/écriture. Ceux-ci font le fichier IO code beaucoup plus agréable par éviter le terrible regard de code-erreur mécanismes (séquence de si-états et laid, tandis que des boucles, que vérifier le code d'erreur après chaque opération).
En règle générale, vous devriez préférer C++ opérateurs, ils sont:
-- Type de coffre-fort. Vous ne risquez pas de passer un double où le format
appels pour un int.
-- Extensible. Vous pouvez écrire votre propre introduire et
extracters, et de les utiliser.
-- Extensible. Vous pouvez définir vos propres manipulateurs (avec
spécifiques à l'application logique du sens), et de les utiliser. Si vous
souhaitez modifier le format de tous les WidgitNumber
(en interne, un int) de votre sortie, vous modifiez l'
manipulateur; vous n'avez pas à trouver tous les format de
états où les %d est un WidgitNumber.
-- Extensible. Vous pouvez écrire votre propre puits et des sources, et
ceux-ci peuvent transférer à d'autres puits et des sources, de filtrage ou de
l'expansion de l'entrée ou de la sortie désirée.
(FWIW: je ne pense pas que j'ai jamais écrit une application qui
n'utilisez pas de custom >> et << opérateurs, de la coutume, des manipulateurs, et
personnalisé streambuf de l'.)
Est-il considéré comme "mauvaise pratique" impliquer les fonctions C dans les projets C++?
Pas. Les fonctions C sont souvent utilisés dans les projets C++. Concernant les cours d'eau, Google C++ Guide De Style, par exemple, recommande de les utiliser que dans des cas limités tels que "ad-hoc, local, lisible par l'homme et ciblées par rapport à d'autres développeurs plutôt qu'à des utilisateurs finaux".
Quels sont les avantages de l'utilisation des cours d'eau de style C IO accès?
Les principaux avantages sont le type de la sécurité et de l'extensibilité. Cependant, C++ ruisseaux ont de sérieux problèmes, voir les réponses à cette question tels que des problèmes avec la localisation, la mauvaise erreur de déclaration, le code de ballonnements et des problèmes de performances dans certaines implémentations.