Topic: move semantics and stringstream
Author: "Bronek Kozicki" <brok@rubikon.pl>
Date: Fri, 14 Oct 2005 08:57:55 CST Raw View
"Joe Gottman" <jgottman@carolina.rr.com> wrote:
> If we do give stringstream a version of str() that moves instead of
> copies, consider the following function:
I believe that we are discussing proposal to overload str() member
function, based on rvaluness/lvalueness of an object, approximately:
template <typename Char, . . . >
class basic_stringstream : public basic_iostream<Char, . . . >
{ // . . .
basic_string<Char, . . . > str() const &;
basic_string<Char, . . . > str() &&;
};
(there is a space for discussion if "str() const &&;" could be better,
but that's different topic; and I would oppose)
> string foo()
> {
> stringstream s;
> s << "Hello world";
> return s.str();
> }
>
> Which version of str() would be called by the return statement, the
> one that copies or the one that moves? I know that if we were
> returning s, then its move constructor would be called.
as you wrote it, it would be lvalue-qualified overload of str, that is
"str () const &;", because "s" used in return statement is an lvalue.
This would retain existing semantics of str(), that is copy buffer into
newly constructed string. However, have you used:
return move(s).str();
.. then rvalue-qualified overload of "str() &&;" would have been
called, *moving* content of stringstream buffer into newly constructed
string (for details of rvalue- and lvalue- member function qualifier
please see proposal N1821). As the string is a temporary, this content
would have been then moved (through "basic_string(basic_string&&);")
to the variable that actually needs the data.
B.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Sat, 15 Oct 2005 04:47:07 GMT Raw View
In article <g6x3f.4006$pP1.213696@twister.southeast.rr.com>,
jgottman@carolina.rr.com ("Joe Gottman") wrote:
> "Bronek Kozicki" <brok@rubikon.pl> wrote in message
> news:dil29l$ooq$1@inews.gazeta.pl...
> > Marc Schoolderman wrote:
> >> Yechezkel Mett wrote:
> >>
> >>> Stringstreams are often used to format text. Normally, the string
> >>> is then extracted (using stringstream::str()) and the
> >>> stringstream is discarded. As far as I understand str() copies
> >>> the internal string which is a waste, and can be expensive if the
> >>> string is long.
>
>
> If we do give stringstream a version of str() that moves instead of
> copies, consider the following function:
>
> string foo()
> {
> stringstream s;
> s << "Hello world";
> return s.str();
> }
>
> Which version of str() would be called by the return statement, the one that
> copies or the one that moves? I know that if we were returning s, then its
> move constructor would be called.
As the proposal is written today, the copy version. In order to get
what you want you would have to explicitly move:
string foo()
{
stringstream s;
s << "Hello world";
return move(s).str();
}
Or:
string foo()
{
return ((stringstream&&)(stringstream() << "Hello world")).str();
}
It would be cool to get the move implicitly but I fear we might end up
breaking code by doing that. Consider:
A foo()
{
B b;
return bar(b);
}
b is today an lvalue when passed to bar. If we change that to an
rvalue, the code may fail to compile if bar is:
A bar(B&);
I'm not sure how to change the rules so that we would move from s.str(),
but not break bar(b).
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Bronek Kozicki <brok@rubikon.pl>
Date: Sat, 15 Oct 2005 15:30:01 CST Raw View
Howard Hinnant wrote:
> return move(s).str();
> }
> I'm not sure how to change the rules so that we would move from s.str(),
> but not break bar(b).
I think that there is no need to change the core language rules. The
explicit form you presented (cited on top) seems just fine to me
B.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "wpcmame" <wpcmame@hotmail.com>
Date: Mon, 17 Oct 2005 22:10:53 CST Raw View
Why not add a member returning a pair of const iterators to the
internal buffer instead?
It would also be nice with a str()/constructor overload which takes a
pair of iterators. Then you can easily use stringstream with any string
type.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com
Date: 19 Oct 2005 05:30:09 GMT Raw View
Ion Gazta aga wrote:
> Shouldn't we have a way to move also from the string to the
> stringstream? This would definitely eliminate any overhead associated
> with stringstream (which is its single major disavantage comparing to
> the old strstream). We can have a string where our desired value is
> stored (we have full stream formatting framework with zero overhead):
>
> //This string would contain at the end all formatted string
> std::string my_string;
>
> //If we know the string will be quite long, we can reserve
> my_string.reserve(1024*1024*1024/*1 MB*/)
That's 1GB, not 1MB.
> //oss would be our formatting framework
> std::ostringstream oss;
>
> //Now use this my_string resources
> oss.move_from(my_string);
>
> while(/**/)
> oss << a << b << c << d;
>
> //Get back string, no memory allocation/deallocation
> my_string = oss.move_str();
>
> //Pass it to a C-like string
> func(my_string.c_str());
Would it make just as much sense, to change std::string so that it
is a type of stream? Then we could apply operator<<, operator>>,
etc. to it.
Or would the space and/or time overhead affect normal string usage?
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Mon, 24 Oct 2005 15:24:31 GMT Raw View
In article <1129530380.756601.95830@z14g2000cwz.googlegroups.com>,
"wpcmame" <wpcmame@hotmail.com> wrote:
> Why not add a member returning a pair of const iterators to the
> internal buffer instead?
>
> It would also be nice with a str()/constructor overload which takes a
> pair of iterators. Then you can easily use stringstream with any string
> type.
This sounds like a valuable tool in the toolbox to me. But I'm not sure
it should be named stringstream. Such a tool could truly replace
strstream's ability to write to a user-owned buffer and perhaps not be
as fragile strstream. Yet at the same time I would not want to get rid
of one of stringstream's endearing properties: casual use is not going
to leak memory on you. There are no buffer ownership issues with
stringstream, and that's a feature, not a bug.
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Mon, 24 Oct 2005 15:24:46 GMT Raw View
In article <1129677394.241304.311510@z14g2000cwz.googlegroups.com>,
allan_w@my-dejanews.com wrote:
> Would it make just as much sense, to change std::string so that it
> is a type of stream? Then we could apply operator<<, operator>>,
> etc. to it.
>
> Or would the space and/or time overhead affect normal string usage?
The interface of std::string is already widely regarded as a bit
bloated. I'd be nervous about expanding it further.
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "wpcmame" <wpcmame@hotmail.com>
Date: Wed, 26 Oct 2005 10:57:17 CST Raw View
> This sounds like a valuable tool in the toolbox to me. But I'm not sure
> it should be named stringstream. Such a tool could truly replace
> strstream's ability to write to a user-owned buffer and perhaps not be
> as fragile strstream. Yet at the same time I would not want to get rid
> of one of stringstream's endearing properties: casual use is not going
> to leak memory on you. There are no buffer ownership issues with
> stringstream, and that's a feature, not a bug.
Sorry if I was unclear. I meant that stringstream should still own the
buffer. The iterator pair str()/constructor just allows me to use
stringstream with any char sequence without an additional copy to a
basic_string first.
Using a user-owned buffer is better handled via the allocator (if/when
we get an allocator model that supports it).
For performance I would rather see a way to disable the ostream sentry
locks.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Wed, 26 Oct 2005 22:52:27 GMT Raw View
In article <1130320438.629619.227710@g44g2000cwa.googlegroups.com>,
"wpcmame" <wpcmame@hotmail.com> wrote:
> For performance I would rather see a way to disable the ostream sentry
> locks.
What locks?
I'm only half kidding. I assume you're speaking of mutex locks to make
the ostream thread safe? If so, any lock in there doesn't really make
the ostream thread safe. You have to lock the ostream externally anyway
for all but the most trivial uses:
lock lk(cout_mutex);
cout << "The number is " << 5 << '\n';
For my money any lock internal to ostream is a waste of good cpu cycles.
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Thu, 27 Oct 2005 11:18:33 CST Raw View
Howard Hinnant wrote:
> For my money any lock internal to ostream is a waste of good cpu cycles.
There's excessive fear of locking due to some terrible
implementations out there, but simply locking a mutex when
it isn't already locked should be a very cheap operation.
If locking takes more than two machine instructions, the
implementation of locking is broken. Take a look at the
implementation of POSIX threads under QNX, where it's done
right.
John Nagle
Animats
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Thu, 27 Oct 2005 17:21:03 GMT Raw View
John Nagle <nagle@animats.com> wrote:
> Howard Hinnant wrote:
>> For my money any lock internal to ostream is a waste of good cpu cycles.
>
> There's excessive fear of locking due to some terrible
> implementations out there, but simply locking a mutex when
> it isn't already locked should be a very cheap operation.
>
> If locking takes more than two machine instructions, the
> implementation of locking is broken. Take a look at the
> implementation of POSIX threads under QNX, where it's done
> right.
It's been a long time since number of instructions was a good measure
of the running time of a code path. Now an instruction that addresses
memory can take up to about 1000 cycles if it misses all the caches,
and synchronisation instructions such as are needed for locking may
take hundreds of cycles even in the best case.
--
Ben Hutchings
Never put off till tomorrow what you can avoid all together.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 27 Oct 2005 21:58:04 GMT Raw View
John Nagle <nagle@animats.com> writes:
> Howard Hinnant wrote:
>> For my money any lock internal to ostream is a waste of good cpu cycles.
>
> There's excessive fear of locking due to some terrible
> implementations out there, but simply locking a mutex when
> it isn't already locked should be a very cheap operation.
>
> If locking takes more than two machine instructions, the
> implementation of locking is broken. Take a look at the
> implementation of POSIX threads under QNX, where it's done
> right.
Instructions don't have uniform cost. The number of instructions
doesn't matter nearly so much as the number of CPU cycles and the
effect on the cache. IIUC, locking mutexes in multiprocessor
environments requires cache synchronization that can be expensive not
only in the CPU executing the instructions, but all the parallel CPUs.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "wpcmame" <wpcmame@hotmail.com>
Date: 28 Oct 2005 16:00:01 GMT Raw View
>For my money any lock internal to ostream is a waste of good cpu cycles.
std::ostringstream ss
ss << "The number is " << 5 << '\n';
In VC70 the last line will cause the following locks
3 buffer locks (one for each << operation)
2 locale locks to access num_punct and num_put facets.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Yechezkel Mett" <yechezkel@emailaccount.com>
Date: Mon, 10 Oct 2005 14:28:17 CST Raw View
Stringstreams are often used to format text. Normally, the string
is then extracted (using stringstream::str()) and the
stringstream is discarded. As far as I understand str() copies
the internal string which is a waste, and can be expensive if the
string is long. N1682, "Rvalue Reference Recommendations for
Chapter 27", doesn't give any method of moving the string instead
of copying it. It seems a good idea to either add a member
function move_str() which can internally use move(), or provide a
rvalue-this overload to stringstream::str() to do it (relying on
the N1821 proposal).
User code would then look like this:
std::ostringstream oss;
oss << ...
std::string s = oss.move_str();
or
std::ostringstream oss;
oss << ...
std::string s = std::move(oss).str();
Yechezkel Mett
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Mon, 10 Oct 2005 15:49:53 CST Raw View
In article <434a8c60$0$30203$892e7fe2@authen.white.readfreenews.net>,
"Yechezkel Mett" <yechezkel@emailaccount.com> wrote:
> Stringstreams are often used to format text. Normally, the string
> is then extracted (using stringstream::str()) and the
> stringstream is discarded. As far as I understand str() copies
> the internal string which is a waste, and can be expensive if the
> string is long. N1682, "Rvalue Reference Recommendations for
> Chapter 27", doesn't give any method of moving the string instead
> of copying it. It seems a good idea to either add a member
> function move_str() which can internally use move(), or provide a
> rvalue-this overload to stringstream::str() to do it (relying on
> the N1821 proposal).
>
> User code would then look like this:
>
> std::ostringstream oss;
> oss << ...
> std::string s = oss.move_str();
>
> or
>
> std::ostringstream oss;
> oss << ...
> std::string s = std::move(oss).str();
>
> Yechezkel Mett
That is one of the more interesting use-cases I've seen for N1821.
Thanks!
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "=?iso-8859-1?q?Ion_Gazta=F1aga?=" <igaztanaga@gmail.com>
Date: Tue, 11 Oct 2005 16:46:03 CST Raw View
Hi,
Howard Hinnant:
> In article <434a8c60$0$30203$892e7fe2@authen.white.readfreenews.net>,
> "Yechezkel Mett" <yechezkel@emailaccount.com> wrote:
>
>
>> Stringstreams are often used to format text. Normally, the string
>> is then extracted (using stringstream::str()) and the
>> stringstream is discarded. As far as I understand str() copies
>> the internal string which is a waste, and can be expensive if the
>> string is long. N1682, "Rvalue Reference Recommendations for
>> Chapter 27", doesn't give any method of moving the string instead
>> of copying it. It seems a good idea to either add a member
>> function move_str() which can internally use move(), or provide a
>> rvalue-this overload to stringstream::str() to do it (relying on
>> the N1821 proposal).
>>
>> User code would then look like this:
>>
>> std::ostringstream oss;
>> oss << ...
>> std::string s = oss.move_str();
>>
>> or
>>
>> std::ostringstream oss;
>> oss << ...
>> std::string s = std::move(oss).str();
>>
>> Yechezkel Mett
Shouldn't we have a way to move also from the string to the
stringstream? This would definitely eliminate any overhead associated
with stringstream (which is its single major disavantage comparing to
the old strstream). We can have a string where our desired value is
stored (we have full stream formatting framework with zero overhead):
//This string would contain at the end all formatted string
std::string my_string;
//If we know the string will be quite long, we can reserve
my_string.reserve(1024*1024*1024/*1 MB*/)
//oss would be our formatting framework
std::ostringstream oss;
//Now use this my_string resources
oss.move_from(my_string);
while(/**/)
oss << a << b << c << d;
//Get back string, no memory allocation/deallocation
my_string = oss.move_str();
//Pass it to a C-like string
func(my_string.c_str());
Regards,
Ion
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 11 Oct 2005 23:40:54 GMT Raw View
Ion Gazta=F1aga wrote:
>>In article <434a8c60$0$30203$892e7fe2@authen.white.readfreenews.net>,
>> "Yechezkel Mett" <yechezkel@emailaccount.com> wrote:
>>
>>>Stringstreams are often used to format text. Normally, the string
>>>is then extracted (using stringstream::str()) and the
>>>stringstream is discarded. As far as I understand str() copies
>>>the internal string which is a waste, and can be expensive if the
>>>string is long. N1682, "Rvalue Reference Recommendations for
>>>Chapter 27", doesn't give any method of moving the string instead
>>>of copying it. It seems a good idea to either add a member
>>>function move_str() which can internally use move(), or provide a
>>>rvalue-this overload to stringstream::str() to do it (relying on
>>>the N1821 proposal).
>>>
>>> <snip>
>=20
> Shouldn't we have a way to move also from the string to the
> stringstream? This would definitely eliminate any overhead associated
> with stringstream (which is its single major disavantage comparing to
> the old strstream). We can have a string where our desired value is
> stored (we have full stream formatting framework with zero overhead):
>=20
> <snip>
>=20
About the relation of stringstreams with strings, the standard only says
27.7.1/1: "The class basic_stringbuf is derived from basic_streambuf to
associate possibly the input sequence and possibly the output sequence
with a sequence of arbitrary characters. The sequence can be
*initialized from*, or *made available as*, an object of class
basic_string." (emphasys added)
In particular, it doesn't say that the underlying buffer must be kept in
a basic_string object! So there's no point in initializing the stream
with move semantic, because if the underlying buffer is not kept in a
basic_string object, a copy needs to performed anyway. Same for
extraction, I think.
Am I missing something?
Ganesh
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Wed, 12 Oct 2005 18:24:36 GMT Raw View
In article <zIX2f.8636$Pe2.186234@twister2.libero.it>,
AlbertoBarbati@libero.it (Alberto Ganesh Barbati) wrote:
> Ion Gazta=F1aga wrote:
> >>In article <434a8c60$0$30203$892e7fe2@authen.white.readfreenews.net>,
> >> "Yechezkel Mett" <yechezkel@emailaccount.com> wrote:
> >>
> >>>Stringstreams are often used to format text. Normally, the string
> >>>is then extracted (using stringstream::str()) and the
> >>>stringstream is discarded. As far as I understand str() copies
> >>>the internal string which is a waste, and can be expensive if the
> >>>string is long. N1682, "Rvalue Reference Recommendations for
> >>>Chapter 27", doesn't give any method of moving the string instead
> >>>of copying it. It seems a good idea to either add a member
> >>>function move str() which can internally use move(), or provide a
> >>>rvalue-this overload to stringstream::str() to do it (relying on
> >>>the N1821 proposal).
> >>>
> >>> <snip>
> >=20
> > Shouldn't we have a way to move also from the string to the
> > stringstream? This would definitely eliminate any overhead associated
> > with stringstream (which is its single major disavantage comparing to
> > the old strstream). We can have a string where our desired value is
> > stored (we have full stream formatting framework with zero overhead):
> >=20
> > <snip>
> >=20
>=20
> About the relation of stringstreams with strings, the standard only say=
s
> 27.7.1/1: "The class basic stringbuf is derived from basic streambuf t=
o
> associate possibly the input sequence and possibly the output sequence
> with a sequence of arbitrary characters. The sequence can be
> *initialized from*, or *made available as*, an object of class
> basic string." (emphasys added)
>=20
> In particular, it doesn't say that the underlying buffer must be kept i=
n
> a basic string object! So there's no point in initializing the stream
> with move semantic, because if the underlying buffer is not kept in a
> basic string object, a copy needs to performed anyway. Same for
> extraction, I think.
>=20
> Am I missing something?
No, I think you make a good point. However, if the implementor had such=20
an interface to work with, he might be more tempted to use a string=20
internally so that he could take advantage of moving it in and out. He=20
could still use a vector internally (for example), and then his=20
implementation would be forced to copy to/from rvalues. Depending upon=20
the string implementation, this compromise may or may not be worth it.
This (proposed) interface would simply provide more optimization=20
*opportunities*, but not demand said optimizations. From the=20
client-side this means you wouldn't be able to depend upon the move=20
optimizations kicking in. If they did, it would just be gravy=20
(analogous to RVO).
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "=?iso-8859-1?q?Ion_Gazta=F1aga?=" <igaztanaga@gmail.com>
Date: Wed, 12 Oct 2005 13:22:01 CST Raw View
Alberto Ganesh Barbati wrote:
> About the relation of stringstreams with strings, the standard only says
> 27.7.1/1: "The class basic_stringbuf is derived from basic_streambuf to
> associate possibly the input sequence and possibly the output sequence
> with a sequence of arbitrary characters. The sequence can be
> *initialized from*, or *made available as*, an object of class
> basic_string." (emphasys added)
>
> In particular, it doesn't say that the underlying buffer must be kept in
> a basic_string object! So there's no point in initializing the stream
> with move semantic, because if the underlying buffer is not kept in a
> basic_string object, a copy needs to performed anyway. Same for
> extraction, I think.
>
> Am I missing something?
>
> Ganesh
You are right, sorry for my ignorance. I don't know if in general,
stringstreams are very used but many people avoid them (for example in
resource constrained enviroments) because of the underlying performance
hit, when they return a copy of their value stored as an string (even
with the "move" we need a copy). This makes stringstream very heavy
comparing to printf family. I agree that stringstream does not suffer
from buffer overflows but couldn't we have a way to say: "take this
string, format there some values and give me back the result" without
_any_ overhead (allocation/copy)?.
For heavy formatting processing, and long strings, stringstream suffer
a lot when comparing to printf functions. And I think that it is really
a huge waste the way stringstream works. I don't know if making
basic_stringbuf tied with basic_stream should be the correct way, but
if basic_string is the C++ solution to strings, we need some fast
formatting and zero overhead. And thanks for the info in the standard
about stringstreams.
---------------------------------------------------------
I find the following in the net
(http://www.cplusplus.com/ref/iostream/stringstream/):
string str ( ) const;
void str ( string & s );
Get/set the associated string object.
The first syntax returns a copy of the string object currently
associated with the internal buffer.
The second syntax sets a new value for the string object associated
with the buffer.
The buffer of a stringstream is usually associated with an STL string
object.
---------------------------------------------------------
I don't know if all known implementations use std::string as buffer,
but if this is true, maybe requiring a basic_string based buffer is not
too much. It is clear that this is a performance winner. One could use
a buffer implementation based, say, in a deque<char> to avoid
reallocations when adding characters, but if requiring stringstream to
have a std::string buffer is too much, we should have a way to do
overflow-safe, _efficient_ (no extra allocations, no extra copies),
printf-like alternative in C++.
Regards,
Ion
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brok@rubikon.pl (Bronek Kozicki)
Date: Wed, 12 Oct 2005 21:29:58 GMT Raw View
Howard Hinnant wrote:
> No, I think you make a good point. However, if the implementor had such
> an interface to work with, he might be more tempted to use a string
> internally so that he could take advantage of moving it in and out. He
> could still use a vector internally (for example), and then his
> implementation would be forced to copy to/from rvalues. Depending upon
Not really. Look at this example:
template <typename CharT, typename TraitsT = char_traits<CharT>,
typename AllocatorT = allocator<CharT> >
class basic_stringbuf : public basic_streambuf<CharT, TraitsT>
{
_BufferClass<CharT, AllocatorT> buffer_;
public:
// ...
basic_string<CharT, TraitsT, AllocatorT> str() &&
{
return basic_string<CharT, TraitsT, AllocatorT>(move(buffer_));
}
};
B.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: squell@alumina.nl (Marc Schoolderman)
Date: Wed, 12 Oct 2005 21:30:08 GMT Raw View
Yechezkel Mett wrote:
> Stringstreams are often used to format text. Normally, the string
> is then extracted (using stringstream::str()) and the
> stringstream is discarded. As far as I understand str() copies
> the internal string which is a waste, and can be expensive if the
> string is long.
I'll admit not having studied the 'move semantics' or 'rvalue reference'
proposals.
But it seems to me that if you assume a reference counted string, and a
stringbuf maintaining a string internally -- both of which are not
guaranteed, but allowed by the standard -- there's no expensive string
copy or waste involved.
Right?
~Marc.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Bronek Kozicki <brok@rubikon.pl>
Date: Thu, 13 Oct 2005 03:16:49 CST Raw View
Marc Schoolderman wrote:
> Yechezkel Mett wrote:
>
>> Stringstreams are often used to format text. Normally, the string
>> is then extracted (using stringstream::str()) and the
>> stringstream is discarded. As far as I understand str() copies
>> the internal string which is a waste, and can be expensive if the
>> string is long.
>
> I'll admit not having studied the 'move semantics' or 'rvalue reference'
> proposals.
>
> But it seems to me that if you assume a reference counted string, and a
> stringbuf maintaining a string internally -- both of which are not
> guaranteed, but allowed by the standard -- there's no expensive string
> copy or waste involved.
Idea proposed by Yechezkel could be implemented without any of these
assumptions - details of string, stringbuf and stringstream
implementation are not important as long as ownership of managed buffer
may be passed between them. Obvious way of doing it is to provide single
implementation of buffer (implementation detail) that would be used by
all of said classes.
B.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Fri, 14 Oct 2005 02:45:37 GMT Raw View
In article <434d7905$0$718$5fc3050@dreader2.news.tiscali.nl>,
squell@alumina.nl (Marc Schoolderman) wrote:
> Yechezkel Mett wrote:
>
> > Stringstreams are often used to format text. Normally, the string
> > is then extracted (using stringstream::str()) and the
> > stringstream is discarded. As far as I understand str() copies
> > the internal string which is a waste, and can be expensive if the
> > string is long.
>
> I'll admit not having studied the 'move semantics' or 'rvalue reference'
> proposals.
>
> But it seems to me that if you assume a reference counted string, and a
> stringbuf maintaining a string internally -- both of which are not
> guaranteed, but allowed by the standard -- there's no expensive string
> copy or waste involved.
>
> Right?
Reference counted string doesn't get you all the way there. Consider:
std::string ext_buf; // allocate ext_buf.
// fill ext_buf
std::ostringstream os(ext_buf); // shallow refcounted copy.
os << stuff; // modifies internal buffer.
// which forces deep copy
// else ext_buf would be modified.
ext_buf = os.str(); // shallow refcounted copy
// which likely deallocates ext_buf's
// current representation.
ext_buf += stuff; // forces deep copy else
// os.str() is modified.
What Yechezkel has suggested is specifically a transfer of ownership
of the internal buffer to/from the external std::string, as opposed
to a sharing of ownership. This means that one will be able to avoid
all allocations/deallocations for the internal buffer:
std::string ext_buf; // allocate ext_buf
// fill ext_buf
std::ostringstream os(move(ext_buf)); // ext_buf transferred into os
// ext_buf modified at this point,
// probably to "" but that is
// unspecified.
os << stuff; // does not modify ext_buf
ext_buf = move(os).str(); // internal buffer transferred to
// ext_buf. os.str() modified at
// this point probably to "" but
// that is unspecified.
ext_buf += stuff; // does not modify os.str()
In essence, the client gives explicit permission to string/stringstream
to modify the moved-from buffers as it wishes in order to avoid deep
copies. Even if the string is refcounted, this is a win because it
allows the move to release ownership from the source. If the source was
not previously sharing ownership with anyone else then the target
cheaply gets unique ownership. If the source is sharing ownership
because of a previous "copy", then the source must now "execute" that
previous "copy" with a deep copy. The refcounted string will have to
treat a move-from the same as it would any other modification (i.e. you
can only modify strings with unique ownership).
In general I believe that move semantics will favor short-string
optimization over a refcounted implementation, assuming we find all of
the places to enable moving such as this one that Yechezkel has
generously pointed out to us. And the chief reason you need
short-string optimization as opposed to no optimization (imho) is
because the interface of string pretty much demands that it be
represented as a contiguous and null-terminated array. That is, even
the empty string contains one element: charT(0) - your "default" buffer
must always be at least 1 element big. vector<charT> has no such
complication and thus its internal design is typically remarkably
simpler (and will still greatly benefit from move semantics).
Of course I've been reminded many times that there are still good uses
for refcounted structures, especially when either shared ownership
semantics are desired, or when the anticipated sharing is high compared
to the unique modifications that will be made. I just don't believe
that std::string fits into these categories (a const variant of
std::string would be a prime candidate for reference counting though).
<only half joking> We already have several const variants of
std::string in the standard, and they typically are implemented with
reference counting. They can all be found in <stdexcept>.
#include <stdexcept>
#include <iostream>
typedef std::logic_error const_string;
const_string
source()
{
return const_string("this is a const string");
}
int main()
{
const_string cs = source();
std::cout << cs.what();
}
<gag ;-)>
-Howard
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: jgottman@carolina.rr.com ("Joe Gottman")
Date: Fri, 14 Oct 2005 02:46:15 GMT Raw View
"Bronek Kozicki" <brok@rubikon.pl> wrote in message
news:dil29l$ooq$1@inews.gazeta.pl...
> Marc Schoolderman wrote:
>> Yechezkel Mett wrote:
>>
>>> Stringstreams are often used to format text. Normally, the string
>>> is then extracted (using stringstream::str()) and the
>>> stringstream is discarded. As far as I understand str() copies
>>> the internal string which is a waste, and can be expensive if the
>>> string is long.
If we do give stringstream a version of str() that moves instead of
copies, consider the following function:
string foo()
{
stringstream s;
s << "Hello world";
return s.str();
}
Which version of str() would be called by the return statement, the one that
copies or the one that moves? I know that if we were returning s, then its
move constructor would be called.
Joe Gottman
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]