std::string and char pointers

E

Espen Ruud Schultz

Lets say I have a char pointer and an std::string. Is it possible to get a
pointer to the std::string's "content" so that the char pointer can point to
the same text? And vice versa; can I give the std::string a pointer and a
length and then give the std::string control over the pointer and its
content?

I'm basically trying to avoid copying large text between an std::string and
a char pointer, and vice versa.

Is there anyhing in the std::string class to support this?

, Espen
 
A

Andrey Tarasevich

Espen said:
Lets say I have a char pointer and an std::string. Is it possible to get a
pointer to the std::string's "content" so that the char pointer can point to
the same text?

Yes. Read about 'std::string::c_str()' method. But in any case,
'std::string' will not hand over control of the stored string to the
char pointer. 'std::string' will retain full control of the stored
string and may invalidate the pointer returned by a previous call to
'c_str()'.
And vice versa; can I give the std::string a pointer and a
length and then give the std::string control over the pointer and its
content?

No. 'std::string' will make a copy.
I'm basically trying to avoid copying large text between an std::string and
a char pointer, and vice versa.

The best strategy in this case is to use 'std::string' alone and try to
avoid using strings "owned" by char pointers.
 
J

John Dibling

Yes. Read about 'std::string::c_str()' method. But in any case,

No! Sure you can get a char const* from a string, but it's not
guaranteed to be any good after youv'e used it. If you use c_str(),
you have to use that pointer right away, then throw it away. If you
try to save the pointer and use it later, you *could* have a wild
pointer.

Long story short, you need to deep-copy the string. Why do you want a
char* to point to a std::string buffer anyway? Duplication of data is
*usually* a bug.

21.3.6.2 states:

Requires: [snip] Nor shall the p[rogram treat the retuned valuie as a
valid pointer value after any subsequent call to a non-const
function... [snip]
No. 'std::string' will make a copy.

Right, but you could use an auto_ptr instead of a string.

Just what is it you are trying to accomplish?

</dib>

John Dibling
email: dib@substitute_my_full_last_name_here.com
Witty banter omitted for your protection
 
O

Oliver Fleischmann

Lets say I have a char pointer and an std::string. Is it possible to get a
pointer to the std::string's "content" so that the char pointer can point to
the same text? And vice versa; can I give the std::string a pointer and a
length and then give the std::string control over the pointer and its
content?

I'm basically trying to avoid copying large text between an std::string and
a char pointer, and vice versa.

Is there anyhing in the std::string class to support this?

, Espen

std::string.c_str()

Olli
 
A

Andrey Tarasevich

John said:
...

No! Sure you can get a char const* from a string, but it's not
guaranteed to be any good after youv'e used it.

This doesn't make any sense. What is a "used pointer"? There is no such
notion in C++. The pointer obtained from 'c_str()' may be used as many
times as user wants as long as this pointer remains valid. The actions
that invalidate this pointer are clearly described in the specification
of C++ standard library. You actually quite it below.
If you use c_str(),
you have to use that pointer right away, then throw it away.

There in so such things as "right away" and "throw away" in the
specification of standard library. The period this pointer remains valid
is unambiguously defined and depends on the behavior of the concrete
program.
If you
try to save the pointer and use it later, you *could* have a wild
pointer.

Yes, you could. Just like I said in my original message, 'std::string'
doesn't relinquish control of the controlled sequence.
Long story short, you need to deep-copy the string. Why do you want a
char* to point to a std::string buffer anyway?

There are circumstances when you need to deep copy a string and there
are circumstances when you don't need to deep copy a string. It depends
on concrete context.
Duplication of data is *usually* a bug.

I don't understand what you are trying to say. After promoting data
duplication for a while, you suddenly declare it to be a bug.
21.3.6.2 states:

Requires: [snip] Nor shall the p[rogram treat the retuned valuie as a
valid pointer value after any subsequent call to a non-const
function... [snip]

Once again, why did you start response with "No!" and then went on to
basically restate everything that I said in my previous message. Did you
try to read what I said before replying?
Right, but you could use an auto_ptr instead of a string.
...

Huh? Just how do you plan to use an 'auto_ptr' in this case?
 
J

John Dibling

Yes, you could. Just like I said in my original message, 'std::string'
doesn't relinquish control of the controlled sequence.


You are absolutely right. I did not read the words "'std::string'
will retain full control of the stored string and may invalidate the
pointer returned by a previous call to 'c_str()'." in your original
post due to careless reading, and I misunderstood your argument to be
a faulty one. My humble apologies.

</dib>

John Dibling
email: dib@substitute_my_full_last_name_here.com
Witty banter omitted for your protection
 
E

Espen Ruud Schultz

Thanx guys! I'm replying to my own post for several reason, one of them is
to "start over" so to speak...

Anyway, I knew about c_str() but I thought there was another way that didn't
use zero termination. The reson why I needed it not to be zero terminated
was trivial, and after I thought about it, non-existing. So to pop that out
of this subject, c_str() is the way to get a pointer.

Though getting a pointer to the content isn't the main thing I want, but
giving a pointer to an std::string and just say "Here, take this pointer and
the text it points to. This is yours. From now on I want to deal with this
text through you."

This is the abstract of what I'm trying to do, and the reason is simple: I
read a text file from disk and into memory. The function that reads the
file is unimportant, the only thing that matters is that it take a pointer
to an already allocated space in memory. The file in question can be big,
or it can be huge. Either way, I find it unnecessary to have to copy the
text to get it into an std::string object. And since internally,
std::string do keep a single pointer to its content, why not just tell
std::string it can use an existing pointer? That way I don't have to copy
the actual text...

So is there any way for me to give an std::string object an existing pointer
and have the std::string use that pointer exclusively? Though I standard
way to go about this would be best, I really don't care. However, I do not
wish to derive a new class from std::string just for this, and I really just
hope there is a "proper" way to do this...

, Espen
 
J

Jacques Labuschagne

Espen said:
Thanx guys! I'm replying to my own post for several reason, one of them
is to "start over" so to speak...

Anyway, I knew about c_str() but I thought there was another way that
didn't
use zero termination. The reson why I needed it not to be zero terminated
was trivial, and after I thought about it, non-existing. So to pop that
out of this subject, c_str() is the way to get a pointer.

Zero-termination really has nothing to do with it... You want a pointer
to the string's internal representation so you can modify it, yes?
You want to be able to say something like
read_file("foo.txt", my_string.get_internal_buffer());
Right?
That's not how strings work. You can't get that kind of access to the
internals of a string.

You have two options. (a) Copy the text from char* to std::string or (b)
rewrite the function that reads in the file.
 
J

Jim Fischer

Espen said:
Lets say I have a char pointer and an std::string. Is it possible to get a
pointer to the std::string's "content" so that the char pointer can point to
the same text? And vice versa; can I give the std::string a pointer and a
length and then give the std::string control over the pointer and its
content?

I'm basically trying to avoid copying large text between an std::string and
a char pointer, and vice versa.

Is there anyhing in the std::string class to support this?

If I understand your question correctly, I think the answer is "no".

Comment 1) IIRC, there is no standard way to obtain a char* pointer to
the actual "guts" of a std::string object.

[n.b. If you invoke the std::string object's c_str() method, the method
returns a pointer to a const-valued (unmodifiable) char array whose
contents "match" the contents of the std::string object. Note that the
returned pointer becomes invalid "after any subsequent call to a
non-const member function of the class basic_string that designates the
same object as this." [See: 21.3.6/2] For example:
std::string s("hello");
const char *p = s.c_str();
s += '*'; // modifying 's' invalidates the address in 'p'
// 'p' is now invalid
]


Comment 2) AFAIK, the std::string class is not designed to use an
existing char array as the "guts" of a std::string object. IOW, the
contents of the existing char array are copied into the "guts" of the
std::string object.
 
E

Espen Ruud Schultz

Jacques Labuschagne said:
Zero-termination really has nothing to do with it... You want a pointer
to the string's internal representation so you can modify it, yes?

No, I don't. I want a pointer to the std::string's internal representation
so I can read it. Excuse me for being rude, but I already said that the
part about getting the pointer was done with...
You want to be able to say something like
read_file("foo.txt", my_string.get_internal_buffer());
Right?

Nope, wrong again. I want to be able to do something like:

read( "foo.txt", PointerToChar );
String.UseThisPointer( PointerToChar, SizeInformationHere );

, Espen
 
J

Jacques Labuschagne

Espen said:
Nope, wrong again. I want to be able to do something like:

read( "foo.txt", PointerToChar );
String.UseThisPointer( PointerToChar, SizeInformationHere );

As others have said, it can't be done.
 
E

Espen Ruud Schultz

Jacques Labuschagne said:
As others have said, it can't be done.

Yeah, sometimes I find the standard nothing more than limiting. Lots of
"safe guards" and "proper ways". Bah, I'm just annoyed. Thanx though...

, Espen
 
A

Andre Kostur

Yeah, sometimes I find the standard nothing more than limiting. Lots of
"safe guards" and "proper ways". Bah, I'm just annoyed. Thanx
though...

Well, it's only a matter of using the tool the way it's designed. One
problem with your suggestion is that std::string would have no way of
knowing _how_ that buffer was allocated. It could have been allocated
with new, or it could be a local variable, or it could be a pointer to a
string literal, or.... etc.

As a result std::string wouldn't know what operations are possible on
that buffer. As an example, if you passed it a pointer to a string
literal, your program may explode when you tried to modify one of the
characters later.

A second example problem is that your buffer may have been allocated
using a custom allocator of some sort (perhaps it's allocating from some
sort of shared memory), std::string wouldn't know how to deallocate it.
 
S

Stephen Howe

So to pop that out of this subject, c_str() is the way to get a pointer.

Not the only way. data() will do so as well without appenidng a terminating
0.

Stephen Howe
 
J

Jon Bell

If I understand your question correctly, I think the answer is "no".

Comment 1) IIRC, there is no standard way to obtain a char* pointer to
the actual "guts" of a std::string object.

I think the "guts" are implementation-dependent anyway. The internal
representation of std::string data might be something simple like a
dynamically allocated array of char, or it might be something more
complicated that is optimized for dealing with large strings, depending on
whose version of the standard library you're using.
 
J

John Harrison

Espen Ruud Schultz said:
Lets say I have a char pointer and an std::string. Is it possible to get a
pointer to the std::string's "content" so that the char pointer can point to
the same text? And vice versa; can I give the std::string a pointer and a
length and then give the std::string control over the pointer and its
content?

I'm basically trying to avoid copying large text between an std::string and
a char pointer, and vice versa.

Is there anyhing in the std::string class to support this?

, Espen

If you want to be fast and loose try this

string buf(10000);
my_func(&buf[0]);

Strictly illegal but if your string implementation uses contiguous memory
then it may well work.

Another option would be to replace string with vector<char> when the above
really would work.

john
 
E

Espen Ruud Schultz

Stephen Howe said:
Not the only way. data() will do so as well without appenidng a
terminating 0.

Hmm, this makes me wonder. Are you sure data() doesn't have a zero in the
end? If both c_str() and data() return pointers to the internal text, then
if one of them don't have a zero and the other have one, then std::string
must copy and keep at least two versions of its content when someone call
either c_str() or data()...?

It seems like the best way to deal with this is that std::string only keep
one copy of its content and always have a zero termination at the end...

, Espen
 
J

Jacques Labuschagne

Espen said:
I find these problems to be trivial. Of course you have to know your
std::string and code accordingly...

But the standard does not mandate any particular implementation, only the
interface to the implementation. You are of course free to learn the
internals from scratch for each new standard library implementation you
use, provided that those details are available.
It would perhaps be an illuminating experience were you to attempt an
implementation of std::string...
 
J

John Dibling

the only thing that matters is that it take a pointer
to an already allocated space in memory.

Can't be done; std::string isn't a smart pointer. But, you can
reserve() space in the string, then call your function using
string.begin(). This will look to your function like a plain char*,
and you wont have to allocate a special temporary buffer. I believe I
saw this method in Meyers' Effective STL, if anybody would like to
look it up.
std::string do keep a single pointer to its content, why not just tell
std::string it can use an existing pointer? That way I don't have to copy
the actual text...

Because std::string isn't a smart pointer, but you are trying to use
it as if it were. If you really want a smart pointer, use a smart
pointer. std::auto_ptr is a smart pointer you can use, tho I must
admit I personally don't care for it. (Actually, I don't like smart
pointers at all, but that's a topic for another show...)

Repeating another idea many others have suggested, you can also use a
vector<char>, with which you can accomplish anything a string can do,
plus much more. Since memory allocated by vector is guaranteed by the
standard to be contigious, you can use vector::begin() as a char
const*. If you vector::reserve(), you can also use vector::begin()
like a writable char* buffer.
wish to derive a new class from std::string just for this, and I really just

There are tools available. Don't reinvent the wheel.

</dib>

John Dibling
email: dib@substitute_my_full_last_name_here.com
Witty banter omitted for your protection
</dib>

John Dibling
email: dib@substitute_my_full_last_name_here.com
Witty banter omitted for your protection
 
A

Andrey Tarasevich

John said:
...
Repeating another idea many others have suggested, you can also use a
vector<char>, with which you can accomplish anything a string can do,
plus much more. Since memory allocated by vector is guaranteed by the
standard to be contigious, you can use vector::begin() as a char
const*. If you vector::reserve(), you can also use vector::begin()
like a writable char* buffer.
...

You can use '&*v.begin()' or '&v.front()' or '&v[0]' (where 'v' is
'std::vector<char>') as char buffer. But not just 'v.begin()'. In some
implementations 'v.begin()' may return a pointer, but it is not true in
general case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top