-1
string str;    
char *a=str.c_str();

This code is working fine for me but every place else I see this code instead

string str;
char *a=new char[str.length()];
strcpy(a,str.c_str());

I wonder which one is correct and why?

theebugger
  • 77
  • 9
  • 2
    What is `str`? If `str` is `std::string`, neither of them are correct. – MikeCAT Aug 24 '20 at 14:48
  • 1
    "This code is working fine for me" - try turning on compiler warnings! – underscore_d Aug 24 '20 at 14:52
  • The big question is why would someone write code like that (the second snippet)? This is even if the correct number of characters is used in the `new[]` call. It's like the author is begging for a memory leak to occur somewhere. – PaulMcKenzie Aug 24 '20 at 14:55
  • @PaulMcKenzie: You see it a fair bit when working with APIs that take a `char*` as input, even if they purportedly don't modify the buffer. – Bathsheba Aug 24 '20 at 14:56
  • I learned to use `std::vector` for that. – PaulMcKenzie Aug 24 '20 at 14:58
  • Be careful because `std::vector` don't automatically add null character at end of the "strings". – MikeCAT Aug 24 '20 at 14:59
  • In the very limited context provided, the two snippets do not have a dangling pointer problem. There may be dangling pointer problems elsewhere, in the code not provided. A [mcve] would be helpful to properly answer the question. – Eljay Aug 24 '20 at 15:08

3 Answers3

3

Assuming that the type of str is std::string, neither of the code is are correct.

char *a=str.c_str();

is invalid because c_str() will return const char* and removing const without casting (usually const_cast) is invalid.

char *a=new char[str.length()];
strcpy(a,str.c_str());

is invalid because str.length() don't count the terminating null-character while allocating for terminating null-character is required to use strcpy().

There are no dangling pointer problem in code posted here because no pointers are invalidated here.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • Note that std::string::length doesn't traverse the string - the standard requires it is O(1). It's possible the string contains 0 values in its buffer. `strcpy` would stop at the first 0 in `str`. Hence the behaviour is not necessarily undefined, depending on how `str` is set up. – Bathsheba Aug 24 '20 at 14:56
1

The two code segments do different things.

The first assigns the pointer value of str to your new c-tpye string, and implicitly converts from const char*(c_str() return type) to char*, which is wrong. If you were to change your new string you would face an error. Even if c_str() returned char*, altering the new string would also make changes in str.

The second on the other hand creates a new c-type string from the original string, copying it byte-by-byte to the new memory allocated for your new string. Although the line of code you wrote is incorrect, as it does not cover the terminating null character of a c-type string \0. In order to fix that, allocate 1 extra byte for it:

char *a=new char[str.length()+1];

After copying the data from the first string to your new one, making alterations to it will not result in changes in the original str.

Irad Ohayon
  • 174
  • 6
  • 1
    So does it mean that c_str() just returns back the address where the char array for string class is stored (and thus it has to mark it const, so that we don't mess with it)? – theebugger Aug 24 '20 at 15:21
  • 1
    @Saqib Exactly. You can use that pointer to offset the character array using pointer arithmetics, but you shan't treat it as a primitive type for assignment. Further read on Pointer Semantics to be clear on what you can and cannot do with it. – Irad Ohayon Aug 24 '20 at 15:37
0

Possibly.

Consider this.

char const* get_string() {
    string str{"Hello"};    
    return str.c_str();
}

That function returns a pointer to the internal value of str, which goes out of scope when the function returns. You have a dangling pointer. Undefined behaviour. Watch out for time-travelling nasal monkeys.

Now consider this.

char const* get_string() {
    string str{"Hello"};
    char const* a = new char[str.length()+1];
    strcpy(a, str.c_str());
    return a;
}

That function returns a valid pointer to a valid null-terminated C-style string. No dangling pointer. If you forget to delete[] it you will have a memory leak, but that's not what you asked about.

The difference is one of object lifetime. Be aware of scope.

Stephen M. Webb
  • 1,705
  • 11
  • 18