Pointeurs et chaînes C ++
J'apprends le C++, et je suis un peu confus sur les pointeurs (en particulier dans le code source suivant). Mais d'abord, je continue de vous montrer ce que je sais (et puis qui contraste avec le code par rapport à cela parce que j'ai l'impression que si il y a quelques contradictions qui se passe).
Ce que je sais:
int Age = 30;
int* pointer = &Age;
cout << "The location of variable Age is: " << pointer << endl;
cout << "The value stored in this location is: " << *pointer << endl;
Pointeurs de tenir des adresses de mémoire. À l'aide de l'indirection (déréférencement) opérateur ( * ), vous pouvez accéder à ce qui est stocké dans la mémoire de l'emplacement du pointeur. Sur le code de ce livre, je vais avoir du mal à comprendre...
cout << "Enter your name: ";
string name;
getline(cin, name); //gets full line up to NULL terminating character
int CharsToAllocate = name.length() + 1; //calculates length of string input
//adds one onto it to adjust for NULL character
char* CopyOfName = new char[CharsToAllocate];
//pointer to char's called CopyOfName, is given the memory address of the
//beginning of a block
//of memory enough to fit CharsToAllocate. Why we added 1? Because char's need a
//NULL terminating character (cout << "Enter your name: ";
string name;
getline(cin, name); //gets full line up to NULL terminating character
int CharsToAllocate = name.length() + 1; //calculates length of string input
//adds one onto it to adjust for NULL character
char* CopyOfName = new char[CharsToAllocate];
//pointer to char's called CopyOfName, is given the memory address of the
//beginning of a block
//of memory enough to fit CharsToAllocate. Why we added 1? Because char's need a
//NULL terminating character (\0)
strcpy(CopyOfName, name.c_str()); //copies the string name, into a pointer?
cout << "Dynamically allocated buffer contains: " << CopyOfName << endl;
delete[] CopyOfName; //always delete a pointer assigned by new to prevent memory leaks
)
strcpy(CopyOfName, name.c_str()); //copies the string name, into a pointer?
cout << "Dynamically allocated buffer contains: " << CopyOfName << endl;
delete[] CopyOfName; //always delete a pointer assigned by new to prevent memory leaks
De sortie:
Enter your name: Adam
Dynamically allocated buffer contains: Adam
Les commentaires dans le code ci-dessus sont mes commentaires. Mon problème commence avec strcpy
. Pourquoi est - name.c_str()
copié dans un pointeur CopyOfName
? Est-ce à dire que toutes les chaînes sont essentiels pointeurs? Donc, comme
string test = "Bonjour le monde";
Est en fait un pointeur pointant vers l'emplacement mémoire où "H" est stocké?
Ensuite, pourquoi est-il dans l'imprimé de déclaration à l'aide de CopyOfName
et pas *CopyOfName
? Les pointeurs de tenir des adresses de mémoire? À l'aide de *CopyOfName
serait d'imprimer le contenu de l'emplacement mémoire. J'ai essayé ce Code::Blocks et si l'entrée de texte "Hello World". À l'aide de *CopyOfName
dans l'imprimé de déclaration donnerait juste un "H". Cela fait sens, parce que quand j'ai déclaré que j'avais besoin d'un bloc de mémoire avec la "nouvelle chose", cela renvoie un pointeur sur la première partie du bloc de mémoire allouée dynamiquement.
La seule façon de me réconcilier, c'est si une chaîne est en fait un pointeur.
string testing = "Confused";
cout << testing << endl;
serait d'imprimer le mot "Confus"
Cependant, si j'essaie de compiler
string testing = "Confused";
cout << *testing;
Je reçois un message d'erreur.
En gros, pour résumer ma question, je suis en train d'essayer de comprendre le code avec strcpy
et la cout
déclaration.
source d'informationauteur DWade64 | 2013-12-27
Vous devez vous connecter pour publier un commentaire.
Il semble que vous comprenez ce que le C-style chaînes, mais pour résumer, ils sont tout simplement des tableaux de caractères dans la mémoire, par convention terminée par un caractère nul
\0
. Habituellement, ils sont référencés par l'intermédiaire d'unchar*
pointant vers la première lettre de la chaîne. Lorsqu'ils sont imprimés, généralement les caractères de la chaîne sont imprimés à partir de la première, et l'impression (ou la copie, etc.) s'arrête lorsque la\0
terminator est atteint.Un
std::string
est une classe qui (généralement) encapsule un C-chaîne de style. Cela signifie qu'unstd::string
objet (généralement) dispose d'une salle de style C chaîne de caractères qui est utilisé pour mettre en œuvre ses fonctionnalités. La fonctionstd::string::c_str()
retourne un pointeur vers ce sous-jacente C chaîne de style.Supposons que
char *str;
points pour un style C de la chaîne. Si vous essayez d'exécutercout << *str << endl;
vous l'avez remarqué que seul le premier caractère est imprimé. C'est à cause de C++de surcharge de fonctions. Le type de données de*str
estchar
de sorte que lechar
version decout
est appelé et fidèlement imprime le caractère unique*str
. Pour la compatibilité avec le C-style chaînes, la version decout
qui prend unchar*
comme un argument traite le pointeur comme un C-chaîne de style pour l'impression. Si vouscout
unint*
par exemple, le sous-jacentint
ne sera pas imprimé.Edit: un Autre commentaire:
La raison que votre tentative de déréférencer un
std::string
objet a échoué, c'est que, en effet, il n'est pas un pointeur. Vous pourriez déréférencement de la valeur de retour destd::string::c_str()
et vous obtenez de retour de la premièrechar
de la chaîne.Connexes: Comment est std::string en œuvre?.
En C, les chaînes de caractères sont simplement des tableaux de caractères. Et les matrices de décomposition de pointeurs quand il est utilisé comme argument d'une fonction.
En C++,
std::string
est une classe. Il comprend un style C tableau de caractères à l'intérieur, et c'est ce quec_str()
retourne. Mais la chaîne elle-même n'est pas un pointeur, donc vous ne pouvez pas déréférencement d'elle; vous devez utiliser lac_str()
méthode pour obtenir un pointeur vers le contenu de la chaîne.De répondre aux questions dans l'ordre:
Comme Yu Hao a souligné dans son commentaire, il est important de comprendre la différence entre C++-style de cordes et de style C à cordes. Dans le premier cas, vous avez affaire à un "opaque" de l'objet, tandis que dans le dernier cas, vous êtes essentiellement affaire à un "tableau" de caractères.
Avec C++ objets de chaîne, vous pouvez utiliser le
c_str()
méthode pour obtenir un pointeur (un) C-gamme de style de caractères. En C, un tableau est représentée à l'aide du pointeur vers le début du tableau et les références sont atteints par la fourniture d'un décalage (l'index dans le tableau) à partir de cette adresse de départ. Donc la réponse à la dernière question de ce bundle est "oui", le pointeur de la C-chaîne de style est le pointeur vers le premier caractère 'H'.Parce que l'opérateur
<<
est surchargé de poignée C-strings. La mise en œuvre de cette méthode "ne sait pas quoi faire avec le pointeur.Non, au-dessus de vous avoir un objet appelé
string
. Ce serait vrai pourchar* testing = "Hello World"
. Comme vous pouvez le voir, il est même déclaré comme pointeur et il pointe à la première lettre de la chaîne - H.cout prendre pointeur vers le premier caractère de la chaîne afin d'
CopyOfName
est droit. Dans ce cas, il permet d'imprimer tous les caractères à partir de H, jusqu'à ce qu'il trouve \0 (caractère nul). Des chaînes comme "bonjour" ont fait 6 caractères - 'h', 'e', 'l', 'l', 'o' '\0'Lorsque vous écrivez
*CopyOfName
vous êtes un déréférencement du pointeur this et*CopyOfName
est en fait qu'un seul caractèreLes pointeurs ne sont pas les mêmes que pour les tableaux. Les littéraux de chaîne sont immuables, et quand vous avez un pointeur vers une chaîne littérale, vous pouvez inspecter son contenu, mais en les modifiant en sont un comportement indéfini. Lors de l'utilisation de cette syntaxe:
Le littéral de chaîne est copié dans le tableau. Parce que vous ne spécifiez pas une taille, le compilateur automatiquement déduit. Le
NUL
terminator est automatiquement ajouté. Si vous spécifiez une taille, vous devez vous assurer que la mémoire tampon peut contenir leNUL
terminator. Donc:est une erreur. Si vous utilisez l'attache de l'initialiseur de syntaxe:
Ce qui est une erreur car il n'est pas
NUL
terminator. Si vous utilisezstrcpy
unNUL
terminator le fera pour vous.std::string
fournit deux méthodes de retourner un pointeur vers son contenu sous-jacent:data
etc_str
. Avant C++11, la seule différence estdata
ne comprend pas leNUL
terminator. En C++11, c'est maintenant, de sorte que leur comportement est identique. Parce que le pointeur peut facilement être invalidé, n'est pas sûr à manipuler ces pointeurs. Il n'est pas sûr de fairechar * ptr = str.c_str();
parce que la durée de vie du tableau retourné parc_str
meurt à la semi-colon. Vous devez le copier dans un tampon.Vous poser les bonnes questions en tant qu'apprenant.
Réponses:
string
est un objet, lec_str()
essentiellement retourne un pointeur vers le premiercaractère de la chaîne (de type C)
la chaîne
string
objetcout
affiche la chaîne de caractères. Aussi, le C++ est assez intelligent pour déterminer*testing
est illégalPourquoi est nom.c_str() copiés dans un pointeur CopyOfName?
"nom" est un STL chaîne. C'est un objet, qui est différente de celle d'un c-string. Un c-string est une collection de la mémoire, qui contient des caractères, et a une terminaison null. Donc, si vous êtes à l'aide de chaînes de caractères STL et que vous voulez transformer en c-strings, vous utilisez .c_str() pour obtenir le c-string.
CopyOfName contient assez de mémoire pour contenir le nom, depuis qu'il a été alloué pour le tenir.
cout a une TONNE de choses différentes que vous pouvez utiliser avec <<. Il ressemble peut prendre des char *s (qui sont c-strings) ou les chaînes de caractères STL. Il n'a pas l'air comme il peut prendre des pointeurs vers des chaînes de caractères STL.
Je suis un peu confuse lorsque vous avez mis en place "test" mais je pense que vous êtes de se confondre entre les c-cordes (qui sont des char *s) et STL chaînes, qui sont des objets. Ne vous sentez pas mal, ou à l'abandonner. Ce genre de choses est difficile et prend du temps à démarrer.
Que je vous recommande d'essayer et de comprendre la différence entre les termes "c-string", "char *", "stl chaîne" et peut-être "pointeur vers stl chaîne".
Dans C, où C++ standard des chaînes n'existait pas, char* était le soi-disant "string". Comme vous l'avez remarqué, c'est un tableau de caractères se terminant par un caractère NUL. Juste au sujet de toute la bibliothèque standard fonction qui prend un C-chaîne de style prendra un pointeur vers ladite chaîne, pour deux raisons:
Je pense que ce que vous faites, et d'autres s'il vous plaît corrigez-moi si je me trompe, c'est que vous êtes la copie de votre chaîne de caractères dans une dynamique de char tableau. Donc non tu n'es pas la copier dans un pointeur. La raison pour laquelle un pointeur est en cause, car il ya des tableaux dynamiques nécessitent des pointeurs de répartir la mémoire correctement si je suis en droit.