Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can one initialise std::string with pre-allocated memory?

136 views
Skip to first unread message

bol...@cylonhq.com

unread,
Apr 18, 2018, 9:44:39 AM4/18/18
to
Hi

I'm using a C library, one function of which returns a char* pointer to
memory allocated using malloc(). Is there a way of initialising a standard
string to use this memory directly instead of doing its own allocation and
copy? There answer seems to be no as I can't find anything about it on
stackoverflow or general googling but I wondered if anyone here knows any
better?

Thanks for any info

wyn...@gmail.com

unread,
Apr 18, 2018, 11:01:46 AM4/18/18
to
bol...@cylonhq.com於 2018年4月18日星期三 UTC+8下午9時44分39秒寫道:
IIRC, Bjarne Stroustrup sayed something about this: C++ doesn't prevent
one shoot ones own foot.

bol...@cylonhq.com

unread,
Apr 18, 2018, 11:07:12 AM4/18/18
to
On Wed, 18 Apr 2018 08:01:32 -0700 (PDT)
wyn...@gmail.com wrote:
>bol...@cylonhq.com=E6=96=BC 2018=E5=B9=B44=E6=9C=8818=E6=97=A5=E6=98=9F=E6=
>=9C=9F=E4=B8=89 UTC+8=E4=B8=8B=E5=8D=889=E6=99=8244=E5=88=8639=E7=A7=92=E5=
>=AF=AB=E9=81=93=EF=BC=9A
>> Hi
>>=20
>> I'm using a C library, one function of which returns a char* pointer to
>> memory allocated using malloc(). Is there a way of initialising a standar=
>d=20
>> string to use this memory directly instead of doing its own allocation an=
>d=20
>> copy? There answer seems to be no as I can't find anything about it on=20
>> stackoverflow or general googling but I wondered if anyone here knows any=
>=20
>> better?
>>=20
>> Thanks for any info
>
>IIRC, Bjarne Stroustrup sayed something about this: C++ doesn't prevent
>one shoot ones own foot.

Thanks, very helpful. Do you have any more nuggets of wisdom from your box of
C++ fortune cookies or is that it?

Sam

unread,
Apr 18, 2018, 11:20:24 AM4/18/18
to
The short answer is: no there isn't. You can't find anything because no such
thing exists.

It's a near certainty that your actual problem is not about finding a way to
use preallocated memory for std::string's storage. You're just assuming that
the solution for your actual problem is to have std::string use preallocated
storage, and that's what you're trying to figure out. Perhaps if a
description of your real problem is provided, you might get a suggestion for
an alternative approach that solves it, without using a std::string.


Paavo Helde

unread,
Apr 18, 2018, 11:26:28 AM4/18/18
to
In C++17 there is std::string_view which does not copy the bytes. But
then you need to remember to free the memory by yourself afterwards,
which is a nuisance. Maybe some custom class combining a string_view and
a deleter? Seems a bit like an overkill.

In short, I suggest to just use std::string and forget about the cost of
this copy, until the unlikely case it shows up in the profiler.
Premature optimization is the root of all evil. If your strings are
shorter than a megabyte there should be no problem.


bol...@cylonhq.com

unread,
Apr 18, 2018, 11:41:01 AM4/18/18
to
On Wed, 18 Apr 2018 11:20:09 -0400
Sam <s...@email-scan.com> wrote:
>This is a MIME GnuPG-signed message. If you see this text, it means that
>your E-mail or Usenet software does not support MIME signed messages.
>The Internet standard for MIME PGP messages, RFC 2015, was published in 1996.
>To open this message correctly you will need to install E-mail or Usenet
>software that supports modern Internet standards.
>
>--=_monster.email-scan.com-90947-1524064809-0001
>Content-Type: text/plain; format=flowed; delsp=yes; charset="UTF-8"
>Content-Disposition: inline
>Content-Transfer-Encoding: 7bit
>
>bol...@cylonHQ.com writes:
>
>> Hi
>>
>> I'm using a C library, one function of which returns a char* pointer to
>> memory allocated using malloc(). Is there a way of initialising a standard
>> string to use this memory directly instead of doing its own allocation and
>> copy? There answer seems to be no as I can't find anything about it on
>> stackoverflow or general googling but I wondered if anyone here knows any
>> better?
>
>The short answer is: no there isn't. You can't find anything because no such
>thing exists.
>
>It's a near certainty that your actual problem is not about finding a way to
>use preallocated memory for std::string's storage. You're just assuming that

Isn't it? Oh ok, thanks for your insight.

>the solution for your actual problem is to have std::string use preallocated
>storage, and that's what you're trying to figure out. Perhaps if a
>description of your real problem is provided, you might get a suggestion for
>an alternative approach that solves it, without using a std::string.

I could write the entire application in C if I had to. Oddly enough I prefer to
use C++ as it makes life a bit easier, a string class being part of it.


bol...@cylonhq.com

unread,
Apr 18, 2018, 11:43:06 AM4/18/18
to
On Wed, 18 Apr 2018 18:26:14 +0300
Paavo Helde <myfir...@osa.pri.ee> wrote:
>In C++17 there is std::string_view which does not copy the bytes. But
>then you need to remember to free the memory by yourself afterwards,
>which is a nuisance. Maybe some custom class combining a string_view and
>a deleter? Seems a bit like an overkill.
>
>In short, I suggest to just use std::string and forget about the cost of
>this copy, until the unlikely case it shows up in the profiler.
>Premature optimization is the root of all evil. If your strings are
>shorter than a megabyte there should be no problem.

Problem is the function is called and the data assigned to a string for each
row loaded from a database. Those small inefficiencies add up. However it
looks like either I put up with them or just use C string handling functions.
A pity.

Marcel Mueller

unread,
Apr 18, 2018, 11:50:45 AM4/18/18
to
Indeed, std::string is by definition mutable and therefore cannot
support immutable memory as backend.
It cannot support memory allocated with the /C/ function malloc either
since it uses C++ allocation. But even C++ new char[] won't help since
the allocation strategy is implementation defined and some string
implementations hold small strings in the instance without external
allocation while larger strings are allocated separately.

As work around you can go the other way around and use std::string as
allocator, i.e. malloc replacement, and modify the storage afterwards.
AFAIK there is no undefined behavior in this pattern.

If you intend to deal with string /constants/ then C++17's string_view
come into play (as already mentioned).

In fact I never used any of the options in production code. Either I
have my completely own string implementation that exactly fit my needs
or I simply deal with std::string not concerning myself with details
like that.


Marcel

Paavo Helde

unread,
Apr 18, 2018, 12:19:53 PM4/18/18
to
On 18.04.2018 18:42, bol...@cylonHQ.com wrote:
> On Wed, 18 Apr 2018 18:26:14 +0300
> Paavo Helde <myfir...@osa.pri.ee> wrote:
>> In C++17 there is std::string_view which does not copy the bytes. But
>> then you need to remember to free the memory by yourself afterwards,
>> which is a nuisance. Maybe some custom class combining a string_view and
>> a deleter? Seems a bit like an overkill.
>>
>> In short, I suggest to just use std::string and forget about the cost of
>> this copy, until the unlikely case it shows up in the profiler.
>> Premature optimization is the root of all evil. If your strings are
>> shorter than a megabyte there should be no problem.
>
> Problem is the function is called and the data assigned to a string for each
> row loaded from a database. Those small inefficiencies add up.

They may add up, but as you know everything is relative and in context,
and in this case you have a database operation which is directly
associated and is done *always* together with std::strings construction.
If constructing the needed std::strings takes less than 5% of your C
library function call you can just forget about it as there is nothing
to win.

BTW, if these strings are short, there is a fair chance that std::string
uses SSO with no dynamic memory allocation. OTOH there is probbaly a
malloc()+free() for each string in the C library. If this is the case
then constructing a std::string might have negligible cost compared to
even this malloc()/free() overhead, not to speak about the database
operation.

So, don't guess, measure. Run your app in the profiler and see what pops
up. I have found very surprising things this way.


Mr Flibble

unread,
Apr 18, 2018, 1:45:42 PM4/18/18
to
You have two options IMHO:

1) Use std::string_view and explicit free()
2) Use a custom allocator with std::basic_string rather than the default
one you get with std::string. This allocator should throw an exception if
there is an allocation request and call free() is deallocate() is called.

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That’s what I would say."

Alf P. Steinbach

unread,
Apr 18, 2018, 8:53:48 PM4/18/18
to
No, but you can store it in a `std::unique_ptr` or `std::shared_ptr`
with custom deleter. Maybe write a little wrapper class for that.

Performance note 1: `shared_ptr` adds a dynamic allocation for the
control block.

Performance note 2: **measure** before you dismiss `std::string`.


Cheers & hth.,

- Alf

bol...@cylonhq.com

unread,
Apr 20, 2018, 5:04:32 AM4/20/18
to
On Wed, 18 Apr 2018 17:50:30 +0200
Marcel Mueller <news.5...@spamgourmet.org> wrote:
>On 18.04.18 15.44, bol...@cylonHQ.com wrote:
>> I'm using a C library, one function of which returns a char* pointer to
>> memory allocated using malloc(). Is there a way of initialising a standard
>> string to use this memory directly instead of doing its own allocation and
>> copy? There answer seems to be no as I can't find anything about it on
>> stackoverflow or general googling but I wondered if anyone here knows any
>> better?
>
>Indeed, std::string is by definition mutable and therefore cannot
>support immutable memory as backend.
>It cannot support memory allocated with the /C/ function malloc either
>since it uses C++ allocation. But even C++ new char[] won't help since
>the allocation strategy is implementation defined and some string
>implementations hold small strings in the instance without external
>allocation while larger strings are allocated separately.
>
>As work around you can go the other way around and use std::string as
>allocator, i.e. malloc replacement, and modify the storage afterwards.
>AFAIK there is no undefined behavior in this pattern.

You mean directly modify the memory pointed to by std::string::c_str()?
No no, thats a very bad idea as I found out myself a few years back. Most of
the time it worked, but occasionally it didn't and created obscure bugs.
Sometimes you learn the hard way :)

>If you intend to deal with string /constants/ then C++17's string_view
>come into play (as already mentioned).

I've only just got up to speed with c++11, I don't have the time or the will to
keep playing catch-up with whatever the standards committee are throwing into
the kitchen sink this year, especially given that in the large companies I work
in the C++ compilers are only rarely updated anyway.

Öö Tiib

unread,
Apr 20, 2018, 6:27:46 AM4/20/18
to
On Friday, 20 April 2018 12:04:32 UTC+3, bol...@cylonhq.com wrote:
> On Wed, 18 Apr 2018 17:50:30 +0200
> Marcel Mueller <news.5...@spamgourmet.org> wrote:
> >
> >As work around you can go the other way around and use std::string as
> >allocator, i.e. malloc replacement, and modify the storage afterwards.
> >AFAIK there is no undefined behavior in this pattern.
>
> You mean directly modify the memory pointed to by std::string::c_str()?
> No no, thats a very bad idea as I found out myself a few years back. Most of
> the time it worked, but occasionally it didn't and created obscure bugs.
> Sometimes you learn the hard way :)

It is getting old how the "Snowflakes" generation always misinterprets
whatever others say in worst possible way, then build ugly straw man
arguments out of that misinterpretation and then argue against the
utter nonsense that they themselves just manufactured.

If you need to convert std::basic_string<CharT> to mutable CharT pointer
then use &str[0]. It returns pointer to mutable data unless str was
const (then you should not edit it anyway) and unless str.size() was
0 (then editing that null character pointed at there is obviously undefined
behavior). That idiom is apparently older than members of your generation
and so there is no wonder that you don't know about it. :D

bol...@cylonhq.com

unread,
Apr 20, 2018, 7:01:07 AM4/20/18
to
On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>On Friday, 20 April 2018 12:04:32 UTC+3, bol...@cylonhq.com wrote:
>> On Wed, 18 Apr 2018 17:50:30 +0200
>> Marcel Mueller <news.5...@spamgourmet.org> wrote:
>> >
>> >As work around you can go the other way around and use std::string as
>> >allocator, i.e. malloc replacement, and modify the storage afterwards.
>> >AFAIK there is no undefined behavior in this pattern.
>>
>> You mean directly modify the memory pointed to by std::string::c_str()?
>> No no, thats a very bad idea as I found out myself a few years back. Most of
>> the time it worked, but occasionally it didn't and created obscure bugs.
>> Sometimes you learn the hard way :)
>
>It is getting old how the "Snowflakes" generation always misinterprets
>whatever others say in worst possible way, then build ugly straw man
>arguments out of that misinterpretation and then argue against the
>utter nonsense that they themselves just manufactured.
>
>If you need to convert std::basic_string<CharT> to mutable CharT pointer
>then use &str[0]. It returns pointer to mutable data unless str was

And this ugly hack is guaranteed to work for every implemetation of std::string
is it?

>const (then you should not edit it anyway) and unless str.size() was
>0 (then editing that null character pointed at there is obviously undefined
>behavior). That idiom is apparently older than members of your generation
>and so there is no wonder that you don't know about it. :D

If you had stopped to engage your brain for a minute before writing your
patronising bullshit you might have wondered how many millenials actually post
to usenet or have even heard of it. FWIW I was born way before 1980 and if I
need unwarranted smartass reponses I can just talk to my kid for 5 minutes.

Öö Tiib

unread,
Apr 20, 2018, 7:51:57 AM4/20/18
to
On Friday, 20 April 2018 14:01:07 UTC+3, bol...@cylonhq.com wrote:
> On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
> =?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
> >On Friday, 20 April 2018 12:04:32 UTC+3, bol...@cylonhq.com wrote:
> >> On Wed, 18 Apr 2018 17:50:30 +0200
> >> Marcel Mueller <news.5...@spamgourmet.org> wrote:
> >> >
> >> >As work around you can go the other way around and use std::string as
> >> >allocator, i.e. malloc replacement, and modify the storage afterwards.
> >> >AFAIK there is no undefined behavior in this pattern.
> >>
> >> You mean directly modify the memory pointed to by std::string::c_str()?
> >> No no, thats a very bad idea as I found out myself a few years back. Most of
> >> the time it worked, but occasionally it didn't and created obscure bugs.
> >> Sometimes you learn the hard way :)
> >
> >It is getting old how the "Snowflakes" generation always misinterprets
> >whatever others say in worst possible way, then build ugly straw man
> >arguments out of that misinterpretation and then argue against the
> >utter nonsense that they themselves just manufactured.
> >
> >If you need to convert std::basic_string<CharT> to mutable CharT pointer
> >then use &str[0]. It returns pointer to mutable data unless str was
>
> And this ugly hack is guaranteed to work for every implemetation(sic) of
> std::string is it?

You call that "ugly hack" after accusing others of suggesting to casting
away const from what c_str() returns and admitting that you did it yourself?
Read the fine manual. Yes, it should work for every conforming
implementation of std::basic_string. The std::string is required to be
std::basic_string<char, std::char_traits<char>, std::allocator<char>>

> >const (then you should not edit it anyway) and unless str.size() was
> >0 (then editing that null character pointed at there is obviously undefined
> >behavior). That idiom is apparently older than members of your generation
> >and so there is no wonder that you don't know about it. :D
>
> If you had stopped to engage your brain for a minute before writing your
> patronising bullshit you might have wondered how many millenials(sic) actually
> post to usenet or have even heard of it. FWIW I was born way before 1980
> and if I need unwarranted smartass reponses I can just talk to my kid for 5
> minutes.

You did start posting here unwarranted smartass responses. Those
automatically make all smartass responses to you warranted and also
disqualify you from complaining about allegedly unwarranted smartass
responses to you. So complain about something else if you need to.

bol...@cylonhq.com

unread,
Apr 20, 2018, 9:44:50 AM4/20/18
to
On Fri, 20 Apr 2018 04:51:46 -0700 (PDT)
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>On Friday, 20 April 2018 14:01:07 UTC+3, bol...@cylonhq.com wrote:
>> On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
>> And this ugly hack is guaranteed to work for every implemetation(sic) of
>> std::string is it?
>
>You call that "ugly hack" after accusing others of suggesting to casting

It is an ugly hack.

>away const from what c_str() returns and admitting that you did it yourself?

Yes I did it myself and found out it was a bad idea as I said. But I guess
you think you're perfect and never make mistakes. I've met people like you in
in plenty of companies, usually while having to bug fix their code.

>implementation of std::basic_string. The std::string is required to be
>std::basic_string<char, std::char_traits<char>, std::allocator<char>>

And that explains why it will always work does it? Right.

>> If you had stopped to engage your brain for a minute before writing your
>> patronising bullshit you might have wondered how many millenials(sic)

You always know when someone's run out of argument when they point out typos :)

>You did start posting here unwarranted smartass responses. Those

No I didn't actually - I asked a perfectly reasonable question and got some
smartass responses as a result. I guess like you those authors thought I'd run
off chastened. Well I've been on usenet in various guises since 1991 so thats
not going to happen my friend.

Perhaps you should concentrate on your English comprehension and the ability to
follow threads instead of getting your spellchecker out.

Christiano

unread,
Apr 20, 2018, 2:35:15 PM4/20/18
to
I did a post at std-discussion:

Constructor std::string(char * &&). Why not?
https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/8_xudInYUkk

bol...@cylonhq.com

unread,
Apr 23, 2018, 4:32:22 AM4/23/18
to
On Fri, 20 Apr 2018 11:35:02 -0700 (PDT)
Christiano <chris...@engineer.com> wrote:
>I did a post at std-discussion:
>
>Constructor std::string(char * &&). Why not?
>https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/8_xudInYUkk

Interesting code. I'm not sure what the respondent meant by the string doesn't
type-erase the memory deallocation operation. The type will always be a char
so I don't see why that should be an issue.

Bo Persson

unread,
Apr 23, 2018, 5:54:19 AM4/23/18
to
The issue is that the allocator is part of the std::string type. So it
calls std::allocator<char>::deallocate to release the memory. Not
delete, or delete[], or free, or whatever else might be needed.


And if you try some other allocator, you get std::string<char,
special_allocator> which is a different type not compatible with the
normal std::string.


Bo Persson

bol...@cylonhq.com

unread,
Apr 23, 2018, 6:24:47 AM4/23/18
to
On Mon, 23 Apr 2018 11:54:09 +0200
Bo Persson <b...@gmb.dk> wrote:
>On 2018-04-23 10:32, bol...@cylonHQ.com wrote:
>> On Fri, 20 Apr 2018 11:35:02 -0700 (PDT)
>> Christiano <chris...@engineer.com> wrote:
>>> I did a post at std-discussion:
>>>
>>> Constructor std::string(char * &&). Why not?
>>>
>https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/8_xudInYUkk
>>
>> Interesting code. I'm not sure what the respondent meant by the string
>doesn't
>> type-erase the memory deallocation operation. The type will always be a char
>> so I don't see why that should be an issue.
>>
>
>The issue is that the allocator is part of the std::string type. So it
>calls std::allocator<char>::deallocate to release the memory. Not
>delete, or delete[], or free, or whatever else might be needed.

But if constructed with a pointer it could just set a flag so it would know
to use delete or free(). Its not rocket science.

Bo Persson

unread,
Apr 23, 2018, 9:45:15 AM4/23/18
to
It could, but that requires extra storage and additional tests in the
code. And not only for deleting the buffer, but also when moving,
swapping, assigning, reallocating, etc.

How much extra work do we accept for everything else, to be able to
occationally import an existing buffer? Is it a net win for everybody?



Bo Persson

bol...@cylonhq.com

unread,
Apr 23, 2018, 9:48:05 AM4/23/18
to
On Mon, 23 Apr 2018 15:45:01 +0200
Fair point.

Richard

unread,
Apr 23, 2018, 12:16:30 PM4/23/18
to
[Please do not mail me a copy of your followup]

bol...@cylonHQ.com spake the secret code
<pbch99$42o$1...@gioia.aioe.org> thusly:

>On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
>=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>>If you need to convert std::basic_string<CharT> to mutable CharT pointer
>>then use &str[0]. It returns pointer to mutable data unless str was
>
>And this ugly hack is guaranteed to work for every implemetation of std::string
>is it?

Yes, or use str.data() in C++17 or later.

(Prior to C++17, data() returned pointer to const char.)
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Richard

unread,
Apr 23, 2018, 12:17:52 PM4/23/18
to
[Please do not mail me a copy of your followup]

bol...@cylonHQ.com spake the secret code
<pbcqs6$kld$1...@gioia.aioe.org> thusly:

>On Fri, 20 Apr 2018 04:51:46 -0700 (PDT)
>=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>>On Friday, 20 April 2018 14:01:07 UTC+3, bol...@cylonhq.com wrote:
>>> On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
>>> And this ugly hack is guaranteed to work for every implemetation(sic) of
>>> std::string is it?
>>
>>You call that "ugly hack" after accusing others of suggesting to casting
>
>It is an ugly hack.

"hack" implies that it is not officially supported behavior. This is
not true.

std::vector<char> f;
f.push_back('x');
char *x = &f[0];

and ditto for std::string, has been valid semantics and syntax since
C++98.

james...@verizon.net

unread,
Apr 23, 2018, 1:29:55 PM4/23/18
to
On Monday, April 23, 2018 at 12:17:52 PM UTC-4, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> bol...@cylonHQ.com spake the secret code
> <pbcqs6$kld$1...@gioia.aioe.org> thusly:
>
> >On Fri, 20 Apr 2018 04:51:46 -0700 (PDT)
> >=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
> >>On Friday, 20 April 2018 14:01:07 UTC+3, bol...@cylonhq.com wrote:
> >>> On Fri, 20 Apr 2018 03:27:34 -0700 (PDT)
> >>> And this ugly hack is guaranteed to work for every implemetation(sic) of
> >>> std::string is it?
> >>
> >>You call that "ugly hack" after accusing others of suggesting to casting
> >
> >It is an ugly hack.
>
> "hack" implies that it is not officially supported behavior. This is
> not true.
>
> std::vector<char> f;
> f.push_back('x');
> char *x = &f[0];
>
> and ditto for std::string, has been valid semantics and syntax since
> C++98.

Can you cite text from the standard allowing x to be used to access the
other elements of the string? I'm not saying that there's no relevant
text - but I haven't been able to find it.

std::basic_string<> (24.3.2.p3) and std::array<> (27.4.7.1p1) are
required to be contiguous containers (26.2.1p13) which means that their
iterator types must qualify as contiguous iterators (27.2.1p6), and
27.9.2.4p3 imposes similar requirements on std::valarray<> - but those
are the only standard containers for which that is true - std::vector<>
has no such requirement. Even for a contiguous container such as std::basic_string<>, you need to use addressof(), not &, to obtain a
pointer value for which the requirements of 27.2.1p6 apply.

Paavo Helde

unread,
Apr 23, 2018, 5:12:26 PM4/23/18
to
23.3.6.1p2: A vector satisfies [...] requirements [...] for an element
type other than bool, of a contiguous container (23.2.1).

For type char, addressof() is the same as &.

I agree that &s[0] is a bit ugly, but it did work in all known
implementations AFAIK even before C++11 officially forced the strings to
use contiguous storage.

For vector there is the non-const data() overload, which was missing for
some reason for string. This was probably an oversight as in C++17 the
non-const data() is added also to strings:
http://en.cppreference.com/w/cpp/string/basic_string/data

So in the future one can just use s.data() instead of &s[0].



Richard

unread,
Apr 23, 2018, 5:41:24 PM4/23/18
to
[Please do not mail me a copy of your followup]

"The elements of a basic_string are stored contiguously, that is,
for a basic_string s, &*(s.begin() + n) == &*s.begin() + n for any n
in [0, s.size()), or, equivalently, a pointer to s[0] can be passed
to functions that expect a pointer to the first element of a CharT[]
array. (since C++11)"

So, guaranteed since C++11, but in practice was always true before
that. If you were really paranoid, e.g. because you needed a
variable-length buffer to be passed to a C-style function, then you
used std::vector<char>, as I have done in the past, and possibly
copied to/from std::string from there. If the copy was unacceptable,
then you brew your own string type as is typical of code bases where
high-performance string processing was normal, e.g. clang/llvm.

Richard

unread,
Apr 23, 2018, 5:42:13 PM4/23/18
to
[Please do not mail me a copy of your followup]

(Richard) legaliz...@mail.xmission.com spake the secret code
<pbljtq$73m$1...@news.xmission.com> thusly:

>[Please do not mail me a copy of your followup]
>
> "The elements of a basic_string are stored contiguously, that is,
> for a basic_string s, &*(s.begin() + n) == &*s.begin() + n for any n
> in [0, s.size()), or, equivalently, a pointer to s[0] can be passed
> to functions that expect a pointer to the first element of a CharT[]
> array. (since C++11)"

Oops, forgot the url, but you probably guessed where it was from
<http://en.cppreference.com/w/cpp/string/basic_string>

bol...@cylonhq.com

unread,
Apr 24, 2018, 4:28:58 AM4/24/18
to
On Tue, 24 Apr 2018 00:12:11 +0300
Paavo Helde <myfir...@osa.pri.ee> wrote:
>For type char, addressof() is the same as &.
>
>I agree that &s[0] is a bit ugly, but it did work in all known
>implementations AFAIK even before C++11 officially forced the strings to
>use contiguous storage.

Would it nor have made more sense for c_str() to return a pointer to mutable
memory rather than taking an address of the first element which seems a
pretty strange way to get the address?

Alf P. Steinbach

unread,
Apr 24, 2018, 5:42:45 AM4/24/18
to
On 24.04.2018 10:28, bol...@cylonHQ.com wrote:
> On Tue, 24 Apr 2018 00:12:11 +0300
> Paavo Helde <myfir...@osa.pri.ee> wrote:
>> For type char, addressof() is the same as &.
>>
>> I agree that &s[0] is a bit ugly, but it did work in all known
>> implementations AFAIK even before C++11 officially forced the strings to
>> use contiguous storage.
>
> Would it nor have made more sense for c_str() to return a pointer to mutable
> memory rather than taking an address of the first element

Consider whether the c_str() buffer should be the string's own main
buffer, so that changes to one of them is directly visible in the other.

If so, then for C++98 and C++03 this would impose a contiguous buffer
requirement. At the time it was envisioned that implementors might
choose a non-contiguous main buffer. It turned out that they didn't, so
C++11 imposed a contiguous buffer requirement, but at the time that was
not known: keeping the possibility of non-contiguous buffer open was
considered important enough to, well, to keep that possibility open.

But if changes to the c_str() buffer should not be reflected in the main
buffer, then a mutable c_str() buffer would require dynamic allocation
and copying of the string contents also in the case where, at the
moment, the main string buffer was contiguous. This would be at odds
with the C++ principle of not paying for what you don't use.

One might however envision wording that would allow, but not require,
changes to be reflected in the main buffer.

But that would make code less portable, and brittle, and possibly
depending on the dynamic internal state of the string for correctness.


> which seems a pretty strange way to get the address?

It's the ordinary way to get the address of an array in C and C++,
except that for raw arrays one usually lets type decays do the job.

There is nothing strange whatsoever about it.

What's /strange/ is doing it in some other way.


Cheeers & hth.,

- Alf

Paavo Helde

unread,
Apr 24, 2018, 6:17:51 AM4/24/18
to
I think for C++17 they had to choose whether to provide a non-const
c_str() or a non-const data(). Other containers already had non-const
data(), so that's one point in favor of data().

Another is that as the name implies c_str() is meant for interfacing
with C, and one does not want to give impression that this interfacing
can be easily done for non-const strings, e.g.

std::string a = "foo";
strcat(a.c_str(), "bar");

bol...@cylonhq.com

unread,
Apr 24, 2018, 6:21:50 AM4/24/18
to
On Tue, 24 Apr 2018 11:42:32 +0200
"Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>But if changes to the c_str() buffer should not be reflected in the main
>buffer, then a mutable c_str() buffer would require dynamic allocation
>and copying of the string contents also in the case where, at the

And why is using the [] operator guaranteed to provide a pointer to a
contiguous buffer? The overload function could simply be doing a mapping
just like c_str().

>It's the ordinary way to get the address of an array in C and C++,

Not in C. Why would you bother with "&str[0]" when you can just use "str"?


Alf P. Steinbach

unread,
Apr 24, 2018, 6:52:55 AM4/24/18
to
The selective out-of-context quoting means you're a troll. Plink.

- Alf


bol...@cyloneaichqueue.com

unread,
Apr 24, 2018, 7:18:59 AM4/24/18
to
On Tue, 24 Apr 2018 12:52:44 +0200
"Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>On 24.04.2018 12:21, bol...@cylonHQ.com wrote:
>> On Tue, 24 Apr 2018 11:42:32 +0200
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>>> But if changes to the c_str() buffer should not be reflected in the main
>>> buffer, then a mutable c_str() buffer would require dynamic allocation
>>> and copying of the string contents also in the case where, at the
>>
>> And why is using the [] operator guaranteed to provide a pointer to a
>> contiguous buffer? The overload function could simply be doing a mapping
>> just like c_str().
>>
>>> It's the ordinary way to get the address of an array in C and C++,
>>
>> Not in C. Why would you bother with "&str[0]" when you can just use "str"?
>
>The selective out-of-context quoting means you're a troll. Plink.

I didn't quote anything out of context. If you realised you made an idiotic
assertion which you now wish to deny, don't accuse someone of being troll just
for pointing it out to you you utter tool.

Oh, and I changed my From: address so I know you'll have read this. Feel
free to respond and dig the hole deeper and or just accept you're an idiot
and move on.

Bo Persson

unread,
Apr 24, 2018, 7:34:49 AM4/24/18
to
On 2018-04-24 12:21, bol...@cylonHQ.com wrote:
> On Tue, 24 Apr 2018 11:42:32 +0200
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>> But if changes to the c_str() buffer should not be reflected in the main
>> buffer, then a mutable c_str() buffer would require dynamic allocation
>> and copying of the string contents also in the case where, at the
>
> And why is using the [] operator guaranteed to provide a pointer to a
> contiguous buffer? The overload function could simply be doing a mapping
> just like c_str().
>

Operator[] must return a reference to the string's internal buffer, to
support s[i] = 'x'.

c_str() was originally allowed to allocate a separate temporary buffer,
or to possibly return a pointer to a shared buffer for copy-on-write
implementations.

Originally it wasn't required for the buffer to be contiguous, but in
practice it was. So the allowance for other options was removed from the
standard, because they had never been used.



Bo Persson

bol...@cylonhq.com

unread,
Apr 24, 2018, 7:54:49 AM4/24/18
to
On Tue, 24 Apr 2018 13:34:37 +0200
Bo Persson <b...@gmb.dk> wrote:
>On 2018-04-24 12:21, bol...@cylonHQ.com wrote:
>> On Tue, 24 Apr 2018 11:42:32 +0200
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>>> But if changes to the c_str() buffer should not be reflected in the main
>>> buffer, then a mutable c_str() buffer would require dynamic allocation
>>> and copying of the string contents also in the case where, at the
>>
>> And why is using the [] operator guaranteed to provide a pointer to a
>> contiguous buffer? The overload function could simply be doing a mapping
>> just like c_str().
>>
>
>Operator[] must return a reference to the string's internal buffer, to
>support s[i] = 'x'.

Not necessarily. [] could simply return a type that has = overloaded. And
for obtaining the value or printing out it could have various standard cast
overloads defined. Thats almost certainly not the way its done but that doesn't
preclude it.

>c_str() was originally allowed to allocate a separate temporary buffer,
>or to possibly return a pointer to a shared buffer for copy-on-write
>implementations.

Given that I had some obscure bugs when I tried to write to the buffer
returned by c_str() when I was younger and didn't know any better, I'd say
some implementations actually did do something like that.

Paavo Helde

unread,
Apr 24, 2018, 9:46:41 AM4/24/18
to
g++ and many other implementations used to have copy-on-write strings
and indeed returned a pointer to a shared buffer. However, this did not
play so well with the multithreading, so in C++11 they introduced new
rules "effectively disallowing copy-on-write implementations" and all
vendors switched away from COW strings.

See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2668.htm
for more details.



Richard

unread,
Apr 24, 2018, 5:00:46 PM4/24/18
to
[Please do not mail me a copy of your followup]

bol...@cylonHQ.com spake the secret code
<pbmprs$1vdm$1...@gioia.aioe.org> thusly:
That's what data() does in later versions of the standard.
0 new messages