Topic: Do multiple calls to std::string::data() return the same pointer?


Author: rani_sharoni@hotmail.com
Date: Sun, 14 Oct 2007 23:38:02 CST
Raw View
On Oct 14, 2:47 pm, Hyman Rosen <hyro...@mail.com> wrote:
> rani_shar...@hotmail.com wrote:
> > I really respect your posts but I don't understand why you are
> > encouraging poor imaginary implementations and draconic usability
> > based on limitations of the standard.
>
> I think Plauger's C++ library took advantage of some of these
> permissions and behaved in ways that were correct according to
> the standard but counterintuitive to some. In any case, this is
> comp.STD.c++, so this is where we discuss what the standard does
> and does not require, and whether it should be changed.

I'm trying to encourage people in positive way saying that the C++
standard is good enough to *allow* high quality implementations and
that's in opposite of saying that the standard can be abused by
useless implementations.
Fortunately, typical C++ standard implementations certainly care about
quality.

Rani

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 15 Oct 2007 14:52:53 GMT
Raw View
rani_sharoni@hotmail.com wrote:
> the standard can be abused by useless implementations.

That is not the correct way of looking at it. These permissions
that you find unfortunate most likely exist because there were
existing implementations that took advantage of them, or because
there were arguments that an implementation might make good use
of them. The string class probably has the most varied set of
implementations of any in the C++ library.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 9 Oct 2007 22:55:10 GMT
Raw View
Greg Herlihy wrote:
> No, operator[] cannot be calling data() because (according to
> [string.require]) calling data() might invalidate references to the string's
> elements, while calling the non-const operator[] does not.

operator[] is part of the implementation, so it can do
whatever it wants. There's no "might".

> It would be perfectly absurd for the C++ Standard to make such behavior
> legal

No. The standard allows string to have a simple implementation, including
having data() and c_str() point directly to the internal representation.
The reason data() and c_str() may invalidate older pointers and iterators
is because an implementation might choose to have the internals of a string
held in a vector<charT>, and c_str() itself can decide to append the '\0',
thus causing the vector to reallocate if it doesn't have the capacity.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Peter C. Chapin" <pchapin@sover.net>
Date: Wed, 10 Oct 2007 21:56:59 CST
Raw View
Hyman Rosen wrote:

> No. The standard allows string to have a simple implementation, including
> having data() and c_str() point directly to the internal representation.
> The reason data() and c_str() may invalidate older pointers and iterators
> is because an implementation might choose to have the internals of a string
> held in a vector<charT>, and c_str() itself can decide to append the '\0',
> thus causing the vector to reallocate if it doesn't have the capacity.

In that case shouldn't the standard specify that c_str() and data()
might throw a std::bad_alloc exception? Or does it already do that
somewhere else?

Peter

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: Thu, 11 Oct 2007 09:59:18 CST
Raw View
Peter C. Chapin wrote:
> In that case shouldn't the standard specify that c_str() and data()
> might throw a std::bad_alloc exception? Or does it already do that
> somewhere else?

Yes, in 17.4.4.8/3:
     "Any other functions defined in the C++ Standard Library that do
      not have an exception-specification may throw implementation-
      defined exceptions unless otherwise specified."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: rani_sharoni@hotmail.com
Date: Fri, 12 Oct 2007 00:15:30 CST
Raw View
On Oct 11, 8:59 am, Hyman Rosen <hyro...@mail.com> wrote:
> Peter C. Chapin wrote:
> > In that case shouldn't the standard specify that c_str() and data()
> > might throw a std::bad_alloc exception? Or does it already do that
> > somewhere else?
>
> Yes, in 17.4.4.8/3:
>      "Any other functions defined in the C++ Standard Library that do
>       not have an exception-specification may throw implementation-
>       defined exceptions unless otherwise specified."

I really respect your posts but I don't understand why you are
encouraging poor imaginary implementations and draconic usability
based on limitations of the standard.

Implementation for which c_str() might throw is practically useless
when out of memory fault tolerance is required. Fortunately there is
no implementation that is not simply returning a pointer to its
already null-terminated internal buffer.

Quality of implementation is very important complementary aspect to
standard compliance and implementations that provides poor realization
of the standard will find themselves *useless*.

Dave Abrahams already explained that 17.4.4.8/3 is due to limitation
of the standardization process and the current specifications are
certainly opened for improvement.

Bjarne Stroustrup's famous Appendix E (Standard Library Exception
Safety) has classic opening quote of you: Everything will work just as
you expect it to, unless your expectations are incorrect.

You can find few "incorrect" expectations of Stroustrup himself in
Appendix E if you wish to follow the standard so strictly (e.g.
iteration over valid sequence can't throw and algorithms themselves
don't throw).

It's still essential for the specifications to meet reasonable
expectations.

Thanks,
Rani

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: Sun, 14 Oct 2007 15:47:57 CST
Raw View
rani_sharoni@hotmail.com wrote:
> I really respect your posts but I don't understand why you are
> encouraging poor imaginary implementations and draconic usability
> based on limitations of the standard.

I think Plauger's C++ library took advantage of some of these
permissions and behaved in ways that were correct according to
the standard but counterintuitive to some. In any case, this is
comp.STD.c++, so this is where we discuss what the standard does
and does not require, and whether it should be changed.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Fri, 5 Oct 2007 13:42:23 CST
Raw View
On 5 Okt., 10:04, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> Assuming nothing is done to invalidate references into a std::string
> (such as calling non-const member functions, etc.), are successive calls
> to std::string::data() guaranteed to return the same value?
>
> For instance, is the following code guaranteed to copy a string:
>
> std::string CopyAString(std::string const& s)
> { return std::string(s.data(), s.data() + s.size()); }
>
> I can't find any wording in the 2003 standards that specifically
> guarantees this.
>
> I do believe this to be the intent, as evidenced by the above expression
> being used in section "22.1.1.4 locale operators".

[lib.basic.string]/5 in 14882-2003 or [string.require]/4 in the N2369
draft are your friend: I quote here the draft version, because it has
been somewhat refined:

"References, pointers, and iterators referring to the elements of a
basic_string
sequence may be invalidated by the following uses of that basic_string
object:
- As an argument to non-member functions swap() (21.3.8.8),
operator>>()
    (21.3.8.9), and getline() (21.3.8.9).
- As an argument to basic_string::swap().
- Calling data() and c_str() member functions. Calling non-const
member
functions, except operator[], at, begin, rbegin, end, and rend.
- Following construction or any of the above uses, except the forms of
insert
and erase that return iterators, the first call to non-const member
functions
operator[], at, begin, rbegin, end, or rend."

(Note: I have removed a typo existing in the recent draft: There
exists
a strayed "item" just before "Calling" - Pete Becker??)

Especially the third and the last bullets are probably most relevant
for you.
Unfortunately the current definition does invalidate your example,
because
it means that c_str() or data() can change it's result on each
invocation (but
see my remarks below!).

Astonishingly the concrete descriptions given in [lib.string.ops] or
[string.ops],
resp. do not seem to enforce such strict constraints:

c_data(), data():
"Requires: [..]. Nor shall the program treat the returned value as a
valid pointer
value after any subsequent call to a non-const member function of the
class
basic_string that designates the same object as this."

IMO the last requirement should either be removed or completed to say
essentially the same as the previous one. From the first mentioned
paragraph
I would conclude that data() and c_str() results can be computed newly
on
each invocation - thereyby invalidating the previous ones.

Considering the also new guarantees given in [string.require]/3:

"The char-like objects in a basic_string object shall be stored
contiguously.
That is, for any basic_string object s, the identity &*(s.begin() + n)
== &*s.
begin() + n shall hold for all values of n such that 0 <= n <
s.size()."

I see no reason to allow invalidation of data() results after a
previous
data() call (not in reference-counting implementations either - these
should only be influenced by the last bullet given in [string.require]/
4).

Can anyone else comment on this?

Greetings from Bremen,

Daniel Kr   gler


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Fri, 5 Oct 2007 13:54:38 CST
Raw View
On 5 Okt., 21:06, Greg Herlihy <gre...@pacbell.net> wrote:
> On Oct 5, 1:04 am, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> Yes, I believe that we can establish such a "guarantee" simply by
> eliminating the alternative: Could two consecutive calls to
> std::string's data() method return two different pointers?

Actually, yes, if the implementation is allowed to "compute" a
new one on each invocation.

> Well, in order for the second call to string::data() to return a
> different pointer than the first call - it must be the case that the
> state of the std::string object itself changed - between the two
> calls. (Otherwise, how would the string object "know" about the first
> call to data() and therefore also know to return a different pointer
> the second time around?)

Unfortunatelty the current wording would allow an invalidation after
each call of data() or c_str(), see [string.require]/4:

"References, pointers, and iterators referring to the elements of a
basic_string sequence may be invalidated by the following uses of
that basic_string object:
[..]
- Calling data() and c_str() member functions.
[..]"

The most reasonable interpretation of the intend seem to be
the following situation:
- Let data return the pointer to the internal representation.
- Now the first call to c_data() happens. Because of an unusual -
but valid - implementation the internal rep. does *not* store
a null-terminator character, therefore a null-terminated
character sequence is created and is further-on returned
by *both* data() and c_str().

No, I don't know such an implementation, but the wording
seems not to guarantee more. And, yes, I'm aware that
both descriptions of data() and c_str() given in [string.ops]
do only say that they are invalidated by non-const
functions, but that directly contradicts the description
given in [string.require]/4.

Greetings from Bremen,

Daniel Kr   gler


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: brangdon@ntlworld.com (Dave Harris)
Date: Fri, 5 Oct 2007 15:58:45 CST
Raw View
greghe@pacbell.net (Greg Herlihy) wrote (abridged):
> Well, in order for the second call to string::data() to return a
> different pointer than the first call - it must be the case that the
> state of the std::string object itself changed - between the two
> calls. (Otherwise, how would the string object "know" about the
> first call to data() and therefore also know to return a
> different pointer the second time around?)

I don't see why it needs to know that. It can just allocate a fresh block
of memory each time, copy its characters into it, and return the result.
The pointer would naturally be different without the object needing to do
anything special.

In an implementation without automated garbage collection, that would
leak memory, but I don't think that means it's not permissible. One
reason is that leaking memory is a QoI issue rather than a conformance
issue. Another is that the standard allows implementations to use garbage
collection.

> In fact we can generalize this principle for all "const-correct"
> classes: a class method declared "const" guarantees that consecutive
> calls of that method will produce unchanging results.

Being const means that the visible state of the object won't change, but
that doesn't necessarily mean the function will return the same result.

     struct Demo {
         char *demo1() const {
             return new char;
         }
         int demo2() const {
             static int counter = 0;
             return ++counter;
         }
     };

Both member functions are const correct. Both return things which are not
part of the visible state of the object.

-- Dave Harris, Nottingham, UK.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Pete Becker <pete@versatilecoding.com>
Date: Fri, 5 Oct 2007 15:58:08 CST
Raw View
On 2007-10-05 03:42:23 -1000, Daniel Kr   gler
<daniel.kruegler@googlemail.com> said:

> - Calling data() and c_str() member functions. Calling non-const
> member
> functions, except operator[], at, begin, rbegin, end, and rend.
>
> (Note: I have removed a typo existing in the recent draft: There
> exists
> a strayed "item" just before "Calling" - Pete Becker??)

Fixed. Thanks. (The "item" should actually be "\item", which starts a
new itemized paragraph)

--
  Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Fri, 5 Oct 2007 18:19:34 CST
Raw View
On Oct 5, 9:54 pm, Daniel Kr   gler <daniel.krueg...@googlemail.com>
wrote:
> On 5 Okt., 21:06, Greg Herlihy <gre...@pacbell.net> wrote:

> > On Oct 5, 1:04 am, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> > Yes, I believe that we can establish such a "guarantee" simply by
> > eliminating the alternative: Could two consecutive calls to
> > std::string's data() method return two different pointers?

> Actually, yes, if the implementation is allowed to "compute" a
> new one on each invocation.

> > Well, in order for the second call to string::data() to return a
> > different pointer than the first call - it must be the case that the
> > state of the std::string object itself changed - between the two
> > calls. (Otherwise, how would the string object "know" about the first
> > call to data() and therefore also know to return a different pointer
> > the second time around?)

> Unfortunatelty the current wording would allow an invalidation after
> each call of data() or c_str(), see [string.require]/4:

> "References, pointers, and iterators referring to the elements of a
> basic_string sequence may be invalidated by the following uses of
> that basic_string object:
> [..]
> - Calling data() and c_str() member functions.
> [..]"

> The most reasonable interpretation of the intend seem to be
> the following situation:
> - Let data return the pointer to the internal representation.
> - Now the first call to c_data() happens. Because of an unusual -
> but valid - implementation the internal rep. does *not* store
> a null-terminator character, therefore a null-terminated
> character sequence is created and is further-on returned
> by *both* data() and c_str().

The original motivation behind all this confusion is to allow
non-contiguous implementations.  In a non-contiguous
implementation, a call to data would either create a special
copy (to be freed when the next non-const function was called),
or change the internal representation (thus, invalidating
iterators and pointers).  I don't think that the actual intent
was that each invocation of data() would return a different
pointer, but I agree that the wording does seem to allow that.

On the other hand, the wording is pretty broken anyway, AND the
committee has decided to require contiguity, and to add a
non-const data() through which you can modify the contents of
the string.  Presumably, the wording concerning data() and
c_str() will be tighted up, and given this new functionality
(which is in fact present internally in all current
implementations), I think it safe to say that multiple calls to
data() will return the same pointer, as long as no other
non-const functions are called in between.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Sat, 6 Oct 2007 12:47:38 CST
Raw View
On 6 Okt., 02:19, James Kanze <james.ka...@gmail.com> wrote:
> The original motivation behind all this confusion is to allow
> non-contiguous implementations.

<nod>  Like SGI's rope class, right?

> On the other hand, the wording is pretty broken anyway, AND the
> committee has decided to require contiguity, and to add a
> non-const data() through which you can modify the contents of
> the string.  Presumably, the wording concerning data() and
> c_str() will be tighted up, and given this new functionality
> (which is in fact present internally in all current
> implementations), I think it safe to say that multiple calls to
> data() will return the same pointer, as long as no other
> non-const functions are called in between.

What makes me feel bad, is that I have quoted the recent
draft (which also has added the continous-guarantee), but
the effects and guarantees of data and c_str() have not yet
been adapted. But you are right, the planned changes are
not complete, e.g. the draft does not yet contain the non-const
data() member function.
Although that seems like muckraking(?) in a beehive: Does
there exists any serious (in the sense: Not my personal,
hand-made, etc.) std::basic_string implementation, which
does *not* use a null-termined representation? (Obviously
I'm starting to hi-jack even the freedom of potentially
computed c_str() returns ;-))

Greetings from Bremen,

Daniel

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@pacbell.net>
Date: Sat, 6 Oct 2007 15:53:06 CST
Raw View
On Oct 5, 12:54 pm, Daniel Kr   gler <daniel.krueg...@googlemail.com>
wrote:
> On 5 Okt., 21:06, Greg Herlihy <gre...@pacbell.net> wrote:
>
> > On Oct 5, 1:04 am, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> > Yes, I believe that we can establish such a "guarantee" simply by
> > eliminating the alternative: Could two consecutive calls to
> > std::string's data() method return two different pointers?
>
> Actually, yes, if the implementation is allowed to "compute" a
> new one on each invocation.

The implementation of std::string data() would eventually have to
allocate memory in order to keep returning fresh pointers. And
intuitively, an object whose memory demands can increase without bound
is not a "const" object. .

For example, calling std::vector::reserve() does not change the number
of objects in the vector or any one of the contained objects
themselves, Nevertheless reserve() is not a const method of
std::vector - because calling std::vector::capacity() might return a
different value after a call to reserve(), than the value that
capacity() would have returned had reserve() not been called at all.

A std::string::data() that returned unique pointers upon each call
would be non-const for the same reason as std::vector reserve().
Except, instead of the capacity() method being affected by a call to
data(), it is the data() method itself that is affected by a (prior)
data() call. In other words, a call to data() would not return the
same pointer as the pointer that data() would have returned - had the
prior call to data() not been made at all.

> > Well, in order for the second call to string::data() to return a
> > different pointer than the first call - it must be the case that > > the
> > state of the std::string object itself changed - between the two
> > calls. (Otherwise, how would the string object "know" about the
> > first
> > call to data() and therefore also know to return a different
> > pointer
> > the second time around?)
>
> Unfortunatelty the current wording would allow an invalidation
> after each call of data() or c_str(), see [string.require]/4:
>
> "References, pointers, and iterators referring to the elements of a
> basic_string sequence may be invalidated by the following uses of
> that basic_string object:
> [..]
> - Calling data() and c_str() member functions.
> [..]"

Note that neither std::string's c_str() or data() methods actually
returns a pointer that refers to "elements of a basic_string
sequence". Instead the two functions return pointers to an allocated
CharT array containing a -copy- of the CharT elements in the sequence
proper. Therefore the quoted paragraph does not apply - so a call to
data() will not invalidate a pointer returned by a prior call to
c_str() and vice versa.

> The most reasonable interpretation of the intend seem to be
> the following situation:
> - Let data return the pointer to the internal representation.

But data() may not return a pointer to the std::string's internal
representation - it must return a pointer to an allocated CharT array.

> - Now the first call to c_data() happens. Because of an unusual -
> but valid - implementation the internal rep. does *not* store
> a null-terminator character, therefore a null-terminated
> character sequence is created and is further-on returned
> by *both* data() and c_str().

The Standard guarantees that data()'s array has already been allocated
once a std::string object has been constructed or copy-assigned a
value. In fact, the purpose of std: data() is to provide clients (read-
only) access to this array (and not access to some other array or
series of other arrays).

> No, I don't know such an implementation, but the wording
> seems not to guarantee more. And, yes, I'm aware that
> both descriptions of data() and c_str() given in [string.ops]
> do only say that they are invalidated by non-const
> functions, but that directly contradicts the description
> given in [string.require]/4.

No, there is no contradiction. As noted above, [string.require]/4 does
not apply to the pointers returned by std::string's data() or c_str()
methods..

Greg



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 9 Oct 2007 17:09:39 GMT
Raw View
Greg Herlihy wrote:
> an object whose memory demands can increase without bound
> is not a "const" object.

But it is perfectly legal for the the implementation of
string to have mutable members in the class, and for the
class to allocate as much memory as it wants.

> Note that neither std::string's c_str() or data() methods actually
> returns a pointer that refers to "elements of a basic_string
> sequence". Instead the two functions return pointers to an allocated
> CharT array containing a -copy- of the CharT elements in the sequence
> proper. Therefore the quoted paragraph does not apply - so a call to
> data() will not invalidate a pointer returned by a prior call to
> c_str() and vice versa.

You are quite wrong. As should be apparent from 20.4.1 and
21.3.4, data() returns a pointer to the internal array of
characters held by the string object.

> But data() may not return a pointer to the std::string's internal
> representation - it must return a pointer to an allocated CharT array.

Why do you think this allocated array cannot be the internal
representation? In fact, as I show below, it must be.

> The Standard guarantees that data()'s array has already been allocated
> once a std::string object has been constructed or copy-assigned a
> value. In fact, the purpose of std: data() is to provide clients (read-
> only) access to this array (and not access to some other array or
> series of other arrays).

Not just read-only, but writable as well, as per 21.3.4.

> No, there is no contradiction. As noted above, [string.require]/4 does
> not apply to the pointers returned by std::string's data() or c_str()
> methods..

No. This code is legal:
     std::string s("Hello.");
     s[5] = '!'; // Now s is "Hello!"
21.3.4 says that
     reference string::operator[](size_type pos)
returns (assuming bounds checks are OK)
     data()[pos]
21.3/6 says that reference is Allocator::reference and
20.4.1 says that allocator<charT>::reference is charT &.
Therefore, it must be the case that data() returns a pointer
to the string's internal representation, because that pointer
can be used to change the string's contents.

And it is perfectly legal (but perverse) for each call to data()
to make a new copy of the string contents and establish that as
the new internal representation, hence the invalidation.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: nevin@eviloverlord.com ("Nevin :-] Liber")
Date: Fri, 5 Oct 2007 08:04:48 GMT
Raw View
Assuming nothing is done to invalidate references into a std::string
(such as calling non-const member functions, etc.), are successive calls
to std::string::data() guaranteed to return the same value?

For instance, is the following code guaranteed to copy a string:

std::string CopyAString(std::string const& s)
{ return std::string(s.data(), s.data() + s.size()); }

I can't find any wording in the 2003 standards that specifically
guarantees this.

I do believe this to be the intent, as evidenced by the above expression
being used in section "22.1.1.4 locale operators".

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@pacbell.net>
Date: Fri, 5 Oct 2007 13:06:38 CST
Raw View
On Oct 5, 1:04 am, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> Assuming nothing is done to invalidate references into a std::string
> (such as calling non-const member functions, etc.), are successive calls
> to std::string::data() guaranteed to return the same value?

Yes, I believe that we can establish such a "guarantee" simply by
eliminating the alternative: Could two consecutive calls to
std::string's data() method return two different pointers?

Well, in order for the second call to string::data() to return a
different pointer than the first call - it must be the case that the
state of the std::string object itself changed - between the two
calls. (Otherwise, how would the string object "know" about the first
call to data() and therefore also know to return a different pointer
the second time around?)

Yet we also know that std::string's data() method is declared "const"
- meaning that calling data() should not change the string object's
state. So, provided that none of the string object's non-const methods
was called between the two calls to data(), then there is nothing left
that could have changed the string object's state. And if the state of
the string object is the same each time that data() is called, then
the pointer that each call of data() returns - must be the same
pointer as well.

In fact we can generalize this principle for all "const-correct"
classes: a class method declared "const" guarantees that consecutive
calls of that method will produce unchanging results. (Of course, it
is possible to implement classes that are not const correct - but if
we cannot rely on the Standard Library classes being const-correct,
then the entire concept of a const class method would have little
practical meaning.)

Greg


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]