7

I am using the std::string type for my string manipulations.

However, sometimes I need to keep the raw char* pointer, even after the original std::string object is destroyed (yes, I know the char* pointer references the HEAP and must eventually be disposed of).

However, looks like there is no way to detach the raw pointer from the string or is it?

Maybe I should use another string implementation?

Thanks.

EDIT

Folks, please do not confuse detaching with copying. The essence of detaching is for the string object to relinquish its ownership on the underlying buffer. So, had the string had the detach method, its semantics would be something like this:

char *ptr = NULL;
{
  std::string s = "Hello world!";
  ptr = s.detach(); // May actually allocate memory, if the string is small enough to have been held inside the static buffer found in std::string.
  assert(s == NULL);
}
// at this point s is destroyed
// ptr continues to point to a valid HEAP memory with the "Hello world!" string in it.
...
delete ptr; // need to cleanup
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
mark
  • 59,016
  • 79
  • 296
  • 580
  • Probable duplicate: [How can I take ownership of a C++ std::string char data without copying and keeping std::string object?](https://stackoverflow.com/q/11301446) – Peter Cordes Nov 11 '21 at 14:08

7 Answers7

7

No, it is not possible to detach the pointer returned by std::string::c_str().

Solution: Make a read-only copy of the string, and ensure that that copy lives at least as long as you need the char* pointer. Then use c_str() on that copy, and it will be valid as long as you want.

If that is not possible, then you won't be able to release the char* either. And any attempt to wrap that pointer in a RAII construction, will only re-invent parts of std::string.

Sjoerd
  • 6,837
  • 31
  • 44
4

std::string allocates through std:allocator (or a template parameter). Even if you could detach the raw storage, you'd have to free it through std::allocator too. And you would of course want a RAII class to do that correctly.

Fortunately, there already is just such a RAII class in the standard libraries. It's called std::string.

The closest thing to a "detach" function, therefore, is swap. It detaches the resources from a string, and stores them in a form from which they can be correctly freed later (i.e., another string). In C++11, move assignment does that too.

std::string raii_for_ptr;
const char *ptr = NULL;
{
     std::string s = "Hello world!";
     raii_for_ptr.swap(s); // or raii_for_ptr = std::move(s)
     ptr = raii_for_ptr.c_str();
     assert(s == "");
}

// no need to cleanup

If your objective is to create for yourself the need to call delete on something, then (a) that's absurd, and hence (b) the standard libraries won't help you. Anyway, you'd probably need delete[] rather than delete. But since strings are not (directly) allocated with new, it's not appropriate to think you can take their memory and free it (directly) with delete[].

So, if your real situation is that you need to pass some pre-existing API a buffer that will be freed with delete[], then you'll have to take a copy, just as if you needed to pass some pre-existing API a buffer that will be freed with free.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

Use c_str() to copy the string into C style string. And then use strcpy()

Vinayak Garg
  • 6,518
  • 10
  • 53
  • 80
0

There are 2 things you can use, depending on what you need. string::c_str () will copy the characters into a C string you can then use for whatever you need. std::data () will return a pointer to the string, but there are 2 issues: a) it is not NULL terminated like a C string, and b) it will go away when the std::string is deleted. So it doesn't stick around after you delete the original object.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • 1
    `c_str` is also gone once you delete the original object. And FWIW in C++11 both `data` and `c_str` return null-terminated strings that point to the internal buffer. – R. Martinho Fernandes Jan 02 '12 at 09:40
0

You can copy your string to a new array of char.

std::string s = "My string";
char *a = new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
Alessandro Pezzato
  • 8,603
  • 5
  • 45
  • 63
0

Since you should always know who owns a particular section of memory the only way to change ownership of a string is to copy it. The simplest way to do this is to just assign the string to another std::string variable. If the ownership changes very often (or you simply cannot clearly determine which specific object is the owner) you'd want to use another implementation of string (or a wrapper for std::string) that supports reference counting, so you don't have to allocate new memory all the time.

Jan Olaf Krems
  • 2,274
  • 1
  • 14
  • 11
0

U can use it as follows:

std::string str = "abcd";
char* cStr = str.c_str();

Thanks...:)

Vinay Jain
  • 2,644
  • 3
  • 26
  • 44
  • What happens with `cStr` when `str` goes off scope? The answer is - it becomes garbage, because `c_str()` does not detach the `char*` pointer, rather it preserves the respective `std::string` as the owner of the buffer. The essence of detaching is that the string relinquish its ownership on the buffer. I am sorry, but your answer is very very wrong. – mark Jan 02 '12 at 12:30
  • @mark: To do that u can take the ownership of the string, will solve the problem. – Vinay Jain Jan 02 '12 at 12:39
  • It is not always possible, hence is my question. – mark Jan 02 '12 at 12:42