22

If I have a pointer that points to a string variable array of chars, is there a difference between typing:

char *name = "name";

And,

string name = "name";
Grobber
  • 99
  • 6
Simplicity
  • 47,404
  • 98
  • 256
  • 385

7 Answers7

35

Yes, there’s a difference. Mainly because you can modify your string but you cannot modify your first version – but the C++ compiler won’t even warn you that this is forbidden if you try.

So always use the second version.

If you need to use a char pointer for whatever reason, make it const:

char const* str = "name";

Now, if you try to modify the contents of str, the compiler will forbid this (correctly). You should also push the warning level of your compiler up a notch: then it will warn that your first code (i.e. char* str = "name") is legal but deprecated.

Yogesh lele
  • 392
  • 4
  • 17
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 2
    @Konrad Rudolph. When you say that "your string variable shouldn’t be a pointer", why is that? Thanks – Simplicity Jan 28 '11 at 09:19
  • 2
    @user588855: Because `std::string` already manages internally the `char *` pointer, you just have to use it as a normal object. Still, to avoid expensive copies, remember to pass it by `const` reference (`const string &`) if you use it as a function parameter and it doesn't need to be modified inside the function. – Matteo Italia Jan 28 '11 at 09:24
  • 1
    @user588855: The simplest explanation is: because *it doesn’t need to be one*. Good C++ code uses as few pointers as possible since pointers always (always!) lead to problems. Therefore, modern C++ is designed so that you rarely need to use pointers at all. – Konrad Rudolph Jan 28 '11 at 09:29
  • @Matteo Italia. So, is `string` the **C++ way** of dealing with strings, and `char*` is the **C way** of dealing with strings? So, what is the solution if I want a pointer to a string in C++? Thanks – Simplicity Jan 28 '11 at 09:29
  • @Konrad Rudolph. Got what you mean. So, I have to try my best in avoiding the use of pointers? – Simplicity Jan 28 '11 at 09:30
  • @user5888855 const char * is used too in C++. See my answer as to why string is better in many situations and therefore why you would use it. – CashCow Jan 28 '11 at 09:32
  • 1
    @user588855: if you really want a pointer to a string then `std::string* p = new std::string("some text");` – Tony Delroy Jan 28 '11 at 09:32
  • @user588855: more or less it's like that. The confusion arises from the fact that string literals (i.e. the `"quoted strings"` you put directly in the code) remain `const char *` even in C++. In general, you don't want to take a pointer to a `string` object (usually you pass it by value - it has a perfectly working copy semantic - or by reference), but nothing stops you from taking a pointer to it with the usual `&` operator - it's just that usually it's not necessary. – Matteo Italia Jan 28 '11 at 09:33
  • So, again, is `char*` the way used to declare strings before the `string` class? – Simplicity Jan 28 '11 at 10:04
  • I was looking at the **Programming in C, Third Edition** book, and gave the following forms of `const`: `char* const charPtr = &c; //charPtr is a constant pointer to a character`. 'const char *charPtr = &c; //charPtr points to a constant character`. Based on that, what is `char const* str = "name";` based on what @Konrad Rudolph suggested? – Simplicity Jan 28 '11 at 10:18
13

For starters, you probably want to change

string *name = "name";

to read

string name = "name";

The first version won't compile, because a string* and a char* are fundamentally different types.

The difference between a string and a char* is that the char* is just a pointer to the sequence. This approach of manipulating strings is based on the C programming language and is the native way in which strings are encoded in C++. C strings are a bit tricky to work with - you need to be sure to allocate space for them properly, to avoid walking off the end of the buffer they occupy, to put them in mutable memory to avoid segmentation faults, etc. The main functions for manipulating them are in <cstring>. Most C++ programmers advise against the use of C-style strings, as they are inherently harder to work with, but they are still supported both for backwards compatibility and as a "lowest common denominator" to which low-level APIs can build off of.

A C++-style string is an object encapsulating a string. The details of its memory management are not visible to the user (though you can be guaranteed that all the memory is contiguous). It uses operator overloading to make some common operations like concatenation easier to use, and also supports several member functions designed to do high-level operations like searching, replacing, substrings, etc. They also are designed to interoperate with the STL algorithms, though C-style strings can do this as well.

In short, as a C++ programmer you are probably better off using the string type. It's safer and a bit easier to use. It's still good to know about C-style strings because you will certainly encounter them in your programming career, but it's probably best not to use them in your programs where string can also be used unless there's a compelling reason to do so.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • This case that I may not getting is since that I'm pointing to a `string` variable, shouldn't the pointer be of the **same** type as the variable it is pointing at? That is `string*`? Thanks – Simplicity Jan 28 '11 at 09:23
  • 1
    @user588855- Unlike C-style strings, C++ strings aren't pointers. They're concrete objects that have their own copy of the string. The string type is designed such that you can initialize a C++ string using a C-style string, so you will want to use a string, not a pointer to a string, in the declaration. It's a bit weird, admittedly, but if you think of it as "I am making a new string equal to this C style string" rather than "I am pointing at an old string" you'll get the correct idea. – templatetypedef Jan 28 '11 at 09:39
9

Yes, the second one isn't valid C++! (It won't compile).

You can create a string in many ways, but one way is as follows:

string name = "name";

Note that there's no need for the *, as we don't need to declare it as a pointer.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • So, if I have a variable of type `string`, is the only type a `pointer` to this variable will have is `char*`? Thanks – Simplicity Jan 28 '11 at 09:20
  • @user588855: nope. `std::string` has nothing to do with `char *` as a type, it's a *class* that encapsulates a C string providing copy semantics, automatic resizing and a lot of other useful stuff. The key here is that a `string` object can be *initialized* with a C-string literal (because it has a constructor that takes a `const char *` as a parameter), then it copies it in its internal buffer that it manages by itself. – Matteo Italia Jan 28 '11 at 09:27
5

char* name = "name" should be invalid but compiles on most systems for backward compatibility to the old days when there was no const and that it would break large amounts of legacy code if it did not compile. It usually gets a warning though.

The danger is that you get a pointer to writable data (writable according to the rules of C++) but if you actually tried writing to it you would invoke Undefined Behaviour, and the language rules should attempt to protect you from that as much as is reasonably possible.

The correct construct is

const char * name = "name";

There is nothing wrong with the above, even in C++. Using string is not always more correct.

Your second statement should really be

std::string name = "name";

string is a class (actually a typedef of basic_string<char,char_traits<char>,allocator<char>) defined in the standard library therefore in namespace std (as are basic_string, char_traits and allocator)

There are various scenarios where using string is far preferable to using arrays of char. In your immediate case, for example, you CAN modify it. So

name[0] = 'N';

(convert the first letter to upper-case) is valid with string and not with the char* (undefined behaviour) or const char * (won't compile). You would be allowed to modify the string if you had char name[] = "name";

However if want to append a character to the string, the std::string construct is the only one that will allow you to do that cleanly. With the old C API you would have to use strcat() but that would not be valid unless you had allocated enough memory to do that.

std::string manages the memory for you so you do not have to call malloc() etc. Actually allocator, the 3rd template parameter, manages the memory underneath - basic_string makes the requests for how much memory it needs but is decoupled from the actual memory allocation technique used, so you can use memory pools, etc. for efficiency even with std::string.

In addition basic_string does not actually perform many of the string operations which are done instead through char_traits. (This allows it to use specialist C-functions underneath which are well optimised).

std::string therefore is the best way to manage your strings when you are handling dynamic strings constructed and passed around at run-time (rather than just literals).

You will rarely use a string* (a pointer to a string). If you do so it would be a pointer to an object, like any other pointer. You would not be able to allocate it the way you did.

CashCow
  • 30,981
  • 5
  • 61
  • 92
1

C++ string class is encapsulating of char C-like string. It is a much more convenient (http://www.cplusplus.com/reference/string/string/).

for legacy you always can "extract" char pointer from string variable to deal with it as char pointer:

    char * cstr;
    string str ("Please split this phrase into tokens");
    cstr = new char [str.size()+1];
    strcpy (cstr, str.c_str());    //here str.c_str() generate null terminated char* pointer
    //str.data() is equivalent, but without null on end
udjin
  • 31
  • 2
0

Yes, char* is the pointer to an array of character, which is a string. string * is the pointer to an array of std::string (which is very rarely used).

string *name = "name"; 

"name" is a const char*, and it would never been converted to a std::string*. This will results compile error.

The valid declaration:

string name = "name";

or

const char* name = "name"; // char* name = "name" is valid, but deprecated
Hoàng Long
  • 10,746
  • 20
  • 75
  • 124
  • 3
    Nope. `string *` (if `string` is `std::string`) is a pointer to an instance of the `std::string` class, and it's quite a rare thing, since you almost always deal with `std::string` instances, not pointers to them (and you don't initialize a `string *` with a string literal). – Matteo Italia Jan 28 '11 at 09:13
  • @Matteo: I know those things, but maybe my explanation sucks. Thanks for the correction. – Hoàng Long Jan 28 '11 at 09:16
  • @Hoàng Long: now it's more or less ok (downvote removed), I don't know if I read it incorrectly or if it was ninja-edited. Still, you should make it more clear that "a string" is different from `string` (alias `std::string`) – Matteo Italia Jan 28 '11 at 09:22
  • 1
    @Hoàng Long: just change the last line to `const char *` and you get my upvote. `:)` (`char *` for string literals is legal but deprecated) – Matteo Italia Jan 28 '11 at 09:30
  • 1
    @Matteo: +1 for your commment, not for the upvote, but to the fact that conversion from const char* to char* is truly deprecated. I used to make a lot of them in university. Thanks – Hoàng Long Jan 28 '11 at 17:59
-1
string *name = "name";

Does not compile in GCC.

Shamim Hafiz - MSFT
  • 21,454
  • 43
  • 116
  • 176