On std::string::c_str() and const_cast<char*>

T

Tom Smith

I hardly dare ask this given the furore in another thread over strings and
const... My problem is this. I am assured that casting away the constness of
the return value of std::string::c_str() is an Error according to the Standard.
But I need to pass it to a function (in an old and unpleasant C library, ugh)
which takes an ordinary char*. What should I do? Is it really necessary to make
a fresh copy of the string?

(I'm not asking this from a performance point of view - the string is rarely
likely to be over 20 characters, and in any case it's certainly not a bottleneck
- but just from an aesthetics one: it's already annoying enough that std::string
doesn't gracefully give me a way of getting a plain char* to its data. (Or am I
wrong?))

Thanks in advance,


Tom
 
F

Frederick Gotham

Tom Smith posted:
I hardly dare ask this given the furore in another thread over strings
and const... My problem is this. I am assured that casting away the
constness of the return value of std::string::c_str() is an Error
according to the Standard. But I need to pass it to a function (in an
old and unpleasant C library, ugh) which takes an ordinary char*. What
should I do? Is it really necessary to make a fresh copy of the string?


Does the unpleasant C library function alter the data? If not, then simply
cast away the constness.

If it does, then you have to consider:

(1) Is it okay to alter the data at the address specified by c_str?

If so,

(1.a) Just cast away the constness and let it be altered.

If not,

(1.b) You'll have to make a copy.
 
M

Marcus Kwok

Tom Smith said:
I hardly dare ask this given the furore in another thread over strings and
const... My problem is this. I am assured that casting away the constness of
the return value of std::string::c_str() is an Error according to the Standard.

As far as I know, as long as you don't ever try to modify the contents
of the string pointed to by c_str(), you should be fine casting away its
constness.
But I need to pass it to a function (in an old and unpleasant C library, ugh)
which takes an ordinary char*. What should I do? Is it really necessary to make
a fresh copy of the string?

As long as you are 100% totally sure that the function won't try to
modify the char* string, then you should be OK.
 
L

loufoque

Tom said:
it's already
annoying enough that std::string doesn't gracefully give me a way of
getting a plain char* to its data. (Or am I wrong?))

All existing implementations use contiguous memory.
It may be a requirement in the next standard also.

So if you really need to you could just code using the assumption that
std::string is contiguous.
 
G

Gavin Deane

Tom said:
I hardly dare ask this given the furore in another thread over strings and
const... My problem is this. I am assured that casting away the constness of
the return value of std::string::c_str() is an Error according to the Standard.

No. It is perfectly legitimate to cast away the const using const_cast.
What is not legitimate (read: undefined behaviour) is to then try and
modify the now apparently non-const data.
But I need to pass it to a function (in an old and unpleasant C library, ugh)
which takes an ordinary char*. What should I do? Is it really necessary to make
a fresh copy of the string?

Depends on what the library function does. If it modifies the data then
you do need to make a copy. The std::string class encapsulates its data
and makes available facilities to modify its data through its public
interface. std::string is not designed to be able to handle anything
outside directly modifying the data outside the scope of its public
interface.

However, many functions that take a C-style string passed as a char* do
not and are never intended to modify the data. Such functions (which
may be C or C++) are written with char* rather than const char* in the
signature for a number of reasons, e.g.

1 The function is a legacy function, written before const existed or
was widely supported
2 The programmer was careless in making the code const-correct
3 The programmer did not know of the existence of const

In a case where the parameter should logically be const, but happens
(e.g. for one of the reason above) not to be declared const, that is
exactly the situation const_cast is designed for. It allows you to keep
your code const-correct, by using const declarations and classes that
manage their own data, while still being able to interface with
const-incorrect legacy APIs.

Remember that a cast does not mean "I can't think of another way to
make this work. I hope it doesn't go wrong". A cast means "Dear
compiler, you won't like this code without a cast, but I know exactly
what I'm doing and why. I am casting off all the safety precautions you
usually give me and assuming full responsibility for the correct
behaviour of this code because in this case I know best".

There is no other way to tell the compiler that the API is incorrect
and should have been written to take a const char*, so if you really do
know best then tell the compiler that with a const_cast.

Gavin Deane
 
T

Tom Smith

Gavin said:
Tom Smith wrote:

<snip>

I am assured that casting away the constness of
Depends on what the library function does. If it modifies the data then
you do need to make a copy. The std::string class encapsulates its data
and makes available facilities to modify its data through its public
interface. std::string is not designed to be able to handle anything
outside directly modifying the data outside the scope of its public
interface.

<more snippage>

Thanks very much Gavin & all other repliers for your advice: very helpful indeed.

- Tom
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top