0
votes

Pourquoi STD :: Array n'a pas d'opérateur T *?

avec des tableaux C, il y a été le cas que simplement nommer un tableau a le même effet que l'écriture & foo [0] pour quelque chose qui approche 50 ans.

Lors de la conversion des tableaux de style C en std :: Array <> Dans un projet, je travaille sur, la grande majorité des "erreurs" apparues étaient dues à la propriété ci-dessus des tableaux C.

Dans tous les cas, la solution était triviale, il suffit d'ajouter .data () . Cependant, il m'a eu lieu qu'un opérateur de code

Y a-t-il une raison technique que cet opérateur n'a pas pu être créé?


10 commentaires

Personnellement, je pense qu'il est plus sûr d'avoir à appeler .data () que ce que nous obtenons avec des tableaux intégrés.


Y a-t-il une bonne raison que cet opérateur n'existe pas? - Super - un autre opérateur étant appelé au moment de l'exécution sans le programmeur en cours de conscience. Si vous remarquez, la majeure partie de la bibliothèque standard C ++ reste à l'écart des opérateurs de casting (peut-être que toute la bibliothèque standard fait). Réaliser que std :: string et en général std :: basique_string <> n'a pas non plus de opérateur caractère * () , et plutôt, Fournissez une fonction c_str () . Mon expérience est qu'un programmeur C ++ portant à plusieurs reprises leur code de code avec des opérateurs de casting ne se connaît pas dans quelles fonctions sont appelées.


@ Sepp2k Ouais, c'est l'opérateur T * Je cherche. J'ai examiné un code de code que je possède depuis des années qui l'a fait pour autre chose. Dans le temps intermédiaire, ma mémoire s'était fanée, nous utilisions opérateur t dans ce contexte permettant un accès direct. La plupart du temps au moins, il fallait quelque peu sur la capacité du compilateur à déduire le type cible au moment de l'exécution. Dans 99% des cas, cela a fonctionné correctement et pour le 1% où il n'a pas eu de .get () méthode pour couvrir. J'ai édité la question de manière appropriée.


Non implicitement en décomposition aux pointeurs est l'un des avantages les plus significatifs de l'utilisation de Std :: Array sur des tableaux de construction.


@ L.f. La conversion implicite n'est pas une "décroissance".


Une excellente question! (Les conversions implicites ne sont pas mauvaises, et non plus d'informations perdent des conversions.)


@Curiousguy Les matrices intégrées sont décrites aux pointeurs. Vous interrogez-vous cette phrase?


@ L.f. std :: Array n'est pas une matrice intégrée et des conversions définies par l'utilisateur ne sont rien comme l'argument décroissant. Vous interrogez-vous cette phrase?


@Cuciousguy J'ai dit "non implicitement en décomposition aux pointeurs est l'un des avantages les plus significatifs de l'utilisation de std :: Array sur des tableaux de construction." Essentiellement, cela signifie que les tableaux intégrés se décomposent implicitement aux pointeurs (c'est vrai) et que std :: graphique ne décrit pas implicitement aux pointeurs (ceci est également vrai). Vous interrogez-vous cette phrase? ;-)


@ L.f. Nope ... vous êtes correct. :RÉ


4 Réponses :


-2
votes

appeler données () code> est une chose à éviter. Il peut être utile d'avoir cette puissance pour (comme dans notre cas dans notre cas de migration de code ou un code optimisé en traitement des tripes), mais elle passe à l'encontre du filet de sécurité std :: grayser code> fournit.

 std::array<int, 2> a{1,2};
 auto* ptr = a.data();
 std::cout << ptr[2]; // boom


3 commentaires

Std :: Array's Opérateur [] n'a pas de vérification des limites. Ergo a.data () [2] est aussi dangereux que A [2] . (** Même si tout compilateur décent attrapera probablement cela)


Ce que j'attribue plus à la conception de la compatibilité que de bien. Pour le code critique de performance, je préférerais si opérateur [] a été modifié et at_unsafe () a été ajouté. Cela de côté: il y a un deuxième aspect: std :: gray porte le type autour de sa déclaration la rendant facilement disponible (à la fois dans la révision du code et à la recherche), le pointeur renvoyé par Data ( ) perd que cela.


Le comportement que vous décrivez est implémenté dans std :: Array :: à . Si vous souhaitez vérifier les limites, préférez à sur opérateur [] .



1
votes

Les données () sont introduites pour avoir une interface similaire sur plusieurs conteneurs STL. Par exemple, STD :: String and STD :: Vecteur fournit également des données () qui donne une adresse du tampon de données réel. SO STD :: L'interface Array a été conçue pour correspondre à cela. Opérateur () que vous suggérez est de manière assez différente et ne semble pas être absolument approprié. Comme ci-dessus, les commentateurs ci-dessus ont également mentionné, plus il est approprié est l'opérateur T * (), mais il ne s'agit toujours pas de la manière dont les concepteurs STL préféraient faire - ils ont introduit des données (). Pourquoi? Peut-être parce que c'est juste plus lisible.


1 commentaires

" opérateur () " Voulez-vous dire opérateur () () ?



5
votes

Les matrices de style C sont des constructions de la taille. Vous pouvez obtenir la taille de la compilation d'un tableau via divers moyens. Cependant, lorsque la matrice se désintègre dans un pointeur, vous perdez cette information de compilation de compilation. Même si le paramètre est un type "tableau", il est toujours toujours un pointeur sans info de taille. Vous pouvez utiliser la programmation de modèles pour préserver la taille si le tableau est passé en tant que paramètre de fonction ( Modèle VOID FUNC (T (& PARAM) [S]) ), mais c'est tout.

Cette décomposition implicite d'un tableau à un pointeur est considérée par de nombreux programmeurs C ++ pour être une faille de conception dans des tableaux de style C. En effet, il ne serait guère déraisonnable de dire que les conversions de pertes ne sont probablement pas des celles qui devraient être implicites. Étant donné que std :: gray est une tentative de fixer autant de défauts de matrices de style C que possible, lui permettant de se décomposer implicitement dans un pointeur serait contre-productif.

par contraste, C ++ 20's std :: span Type fournit une conversion implicite d'un Std :: Array (et des tableaux de style C, entre autres). La raison pour laquelle une telle conversion préserve les informations: pointeur ainsi que la taille. En effet, la conversion peut même préserver la nature de la compilation de cette taille.


Y a-t-il une raison technique que cet opérateur n'a pas pu être créé?

" pourrait pas"? Non.


0 commentaires

0
votes

Y a-t-il une bonne raison que cet opérateur n'existe pas?

Si vous voulez dire pourquoi il n'y a pas de opérateur t * () pour fournir automatiquement la distribution, une (plusieurs) raisons potentielles est exactement cela - l'idée de automatique casting.

Peut-être qu'il serait commode d'avoir le code à l'aide de std :: Array pour simplement compiler correctement en utilisant opérateur t * () , et loin, vous allez avec un programme qui a été construit sans erreurs. Cependant, il y a des implications à cela:

1) L'appel à opérateur t * () est un coût d'exécution potentiel que le programmateur n'a peut-être pas souhaité, mais vient juste pour le trajet. En C ++, l'objectif est de ne payer que ce qui est souhaité et que les opérateurs de coulée s'imposent simplement s'inscrivent à l'encontre de cette idée.

2) opérateur t * () et les opérateurs de casting en général peuvent potentiellement masquer les bugs ou Les goulots d'étranglement dans le code d'exécution, en raison de l'utilisation du programmeur.

Dans mon expérience, demandez à un programmeur avec une base de code jonchée d'opérateurs de casting quelles fonctions sont en cours d'appel, et plus de fois que non, ils ne sont pas sûrs de la voie de leur code, sinon ils sont tout simplement faux ( Et ne le réalisez pas avant de participer à une session de débogage et de voir tous les rebondissements et des virages à être effectués par les opérateurs de coulée apparemment innocents étant invoqués).

Ainsi, il est réputé que le programmeur veuille explicitement "convertir" les données en appelant une fonction telle que data () , et non en utilisant un opérateur ( ) ils n'ont peut-être pas été au courant.


4 commentaires

CASTING n'est jamais automatique: il faut écrire une distribution. Le problème ici est automatique conversions . +1.


En ce qui concerne la performance, avec la façon dont les optimiseurs modernes se comportent, c'est largement un non-problème. Godbolt.org/z/GBRHUL le montre très bien, pour la GCC et MSVC à des optimisations maximales, le la conversion est gratuite.


@Dgnuff - sauf si vous pouvez absolument garantir que l'utilisation d'un tel opérateur n'engagera aucun coût d'exécution dans aucun scénario, il s'agit d'un non-démarreur. C'est pourquoi j'ai dit un potentiel goulot d'étranglement potentiel . Il doit pratiquement être consexpr dans toutes les situations, et cela ne peut être garanti.


@Paulmckenzie que C ++ Construct (qui n'est pas 100% de temps de compilation) n'a-t-il aucune garantie de coût d'exécution?