469,654 Members | 1,857 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,654 developers. It's quick & easy.

problem with string::resize

Hi, in the following code:

string foo("foo");

foo.resize(10);
foo.append("bar");

cout << foo << endl; // output is "foo"

I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?
Thanks,
Metaosp
Feb 12 '06 #1
23 2114

"metaosp" <me*****@gmail.com> skrev i meddelandet
news:11**********************@localhost.localdomai n...
Hi, in the following code:

string foo("foo");

foo.resize(10);
foo.append("bar");

cout << foo << endl; // output is "foo"

I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?


I would expect the output to be "foo\0\0\0\0\0\0\0bar".

The call foo.resize(10) will append enough string::value_type() to
reach the requested size.

How are you checking the result? With something that stops after the
first '\0' ?
Bo Persson

Feb 12 '06 #2
metaosp wrote:
Hi, in the following code:

string foo("foo");

foo.resize(10);
foo.append("bar");

cout << foo << endl; // output is "foo"

I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?
Thanks,
Metaosp


Delete the "foo.resize(10);" line.
It is not necessary, and it appends nul bytes ('\0')
to the end of "foo" to make the total size 10. When you
append "bar" it is appended after the nul bytes.
Unlike C strings, the C++ std::string does not have to
be resized before appending (it handles that on its own),
AND nul bytes ('\0') have no special meaning in a
std::string. A C++ std::string can contain binary data;
Use the length() member of std::string to query the
length of the string (even if it contains binary data).

Regards,
Larry
Feb 12 '06 #3
On Sun, 2006-02-12 at 18:59 +0100, Bo Persson wrote:
"metaosp" <me*****@gmail.com> skrev i meddelandet
news:11**********************@localhost.localdomai n...
Hi, in the following code:

string foo("foo");

foo.resize(10);
foo.append("bar");

cout << foo << endl; // output is "foo"

I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?


I would expect the output to be "foo\0\0\0\0\0\0\0bar".

The call foo.resize(10) will append enough string::value_type() to
reach the requested size.

How are you checking the result? With something that stops after the
first '\0' ?


Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)

Metaosp


Feb 12 '06 #4
In article <11***********************@localhost.localdomain >,
metaosp <me*****@gmail.com> wrote:
On Sun, 2006-02-12 at 18:59 +0100, Bo Persson wrote:
"metaosp" <me*****@gmail.com> skrev i meddelandet
news:11**********************@localhost.localdomai n...
Hi, in the following code:

string foo("foo");

foo.resize(10);
foo.append("bar");

cout << foo << endl; // output is "foo"

I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?


I would expect the output to be "foo\0\0\0\0\0\0\0bar".

The call foo.resize(10) will append enough string::value_type() to
reach the requested size.

How are you checking the result? With something that stops after the
first '\0' ?


Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)


No you don't.

string foo( "foo" );
foo.append( "bar" );
cout << foo << endl;

Does just what you need. "reserve" is a request and nothing more, don't
bother.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 12 '06 #5

"Daniel T." <po********@earthlink.net> wrote in message
news:po******************************@news.east.ea rthlink.net...
Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)


No you don't.

string foo( "foo" );
foo.append( "bar" );
cout << foo << endl;

Does just what you need. "reserve" is a request and nothing more, don't
bother.


With a trivial example such as this that's probably true but
with larger strings you can get a significant speed boost
by reserving the contiguous memory in advance. I've
benchmarked this.

As for it being only a request, when would it be denied?
Feb 13 '06 #6

Larry I Smith wrote in message ...
metaosp wrote:
Hi, in the following code:
string foo("foo");
foo.resize(10);
foo.append("bar");
cout << foo << endl; // output is "foo"
I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?
Thanks,
Metaosp


Delete the "foo.resize(10);" line.
It is not necessary, ***and it appends nul bytes ('\0')***
to the end of "foo" to make the total size 10.


Not if you give it something else: foo.resize( 10, ' ' );

std::string foo( "foo" );
foo.resize(10, ' ' );
foo.append( "bar" );
std::cout << foo << std::endl;
// -- output --:
foo bar

--
Bob R
POVrookie
Feb 13 '06 #7
Daniel T. wrote:

"reserve" is a request and nothing more, don't
bother.


After a call to reserve, capacity() must be at least as large as the
argument in the call.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Feb 13 '06 #8
In article <ax********************@wagner.videotron.net>,
"Duane Hebert" <sp**@flarn2.com> wrote:
"Daniel T." <po********@earthlink.net> wrote in message
news:po******************************@news.east.ea rthlink.net...
Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)
No you don't.

string foo( "foo" );
foo.append( "bar" );
cout << foo << endl;

Does just what you need. "reserve" is a request and nothing more, don't
bother.


With a trivial example such as this that's probably true but
with larger strings you can get a significant speed boost
by reserving the contiguous memory in advance. I've
benchmarked this.


Your assuming that std::string uses contiguous memory, that is not
guaranteed. 'std::string' is not like a vector<char>.
As for it being only a request, when would it be denied?


If std::string is written using a reference counted implementation, or
if it is written like a deque. Also check out sgi's "rope" string.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 13 '06 #9
On Sun, 2006-02-12 at 22:24 +0000, Daniel T. wrote:
metaosp <me*****@gmail.com> wrote:

Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)


No you don't.

string foo( "foo" );
foo.append( "bar" );
cout << foo << endl;

Does just what you need. "reserve" is a request and nothing more, don't
bother.


In this example reserve() is indeed unnecessary, but I actually use
std::string to store a rather large binary data with predetermined size,
I think it would be a good idea to give std::string a hint to avoid
unnecessary reallocating.
Thanks,
--
Metaosp
Feb 13 '06 #10
In article <1139802722.9324.7.camel@jupiter>,
Metaosp <me*****@gmail.com> wrote:
On Sun, 2006-02-12 at 22:24 +0000, Daniel T. wrote:
metaosp <me*****@gmail.com> wrote:

Interesting it is indeed "foo\0\0\0\0\0\0\0bar". I think I need to use
reserve() instead of resize(). Thanks :)


No you don't.

string foo( "foo" );
foo.append( "bar" );
cout << foo << endl;

Does just what you need. "reserve" is a request and nothing more, don't
bother.


In this example reserve() is indeed unnecessary, but I actually use
std::string to store a rather large binary data with predetermined size,
I think it would be a good idea to give std::string a hint to avoid
unnecessary reallocating.


Then use vector.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 13 '06 #11
In article <wo********************@giganews.com>,
Pete Becker <pe********@acm.org> wrote:
Daniel T. wrote:

"reserve" is a request and nothing more, don't
bother.


After a call to reserve, capacity() must be at least as large as the
argument in the call.


class string {
public:
void reserve( int ) { }
size_type capacity() const { return max_size(); }
};

You mean like the above? That is all that is required AFAIK.

The MSDN Library says this of reserve "The request is nonbinding and may
or may not happen." SGI's stl library also says that reserve is "a
request".

What does the standard say about it? I'd be happy to be corrected, but
AFAIK, string's memory is not guaranteed to be contiguous and none of
the member-functions have any complexity guarantees whether reserve is
called or not. In other words reserve is not really guaranteed to do
anything at all for std::string.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 13 '06 #12
* Daniel T.:
* Pete Becker:
* Daniel T.:

"reserve" is a request and nothing more, don't bother.


After a call to reserve, capacity() must be at least as large as the
argument in the call.


class string {
public:
void reserve( int ) { }
size_type capacity() const { return max_size(); }
};

You mean like the above? That is all that is required AFAIK.

The MSDN Library says this of reserve "The request is nonbinding and may
or may not happen." SGI's stl library also says that reserve is "a
request".

What does the standard say about it?


The request is non-binding for /reducing/ the capacity. It is binding
for /increasing/ the capacity. After a call to reserve() a call to
capacity() must be equal or greater, and capacity() is "the size of the
allocated storage in the string".

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 13 '06 #13
Daniel T. wrote:
In article <wo********************@giganews.com>,
Pete Becker <pe********@acm.org> wrote:
Daniel T. wrote:
>
> "reserve" is a request and nothing more, don't
> bother.
>
After a call to reserve, capacity() must be at least as large as the
argument in the call.


class string {
public:
void reserve( int ) { }
size_type capacity() const { return max_size(); }
};

You mean like the above? That is all that is required AFAIK.


No. You are ignoring the fact that the standard specifies a meaning for the
returned value.

The MSDN Library says this of reserve "The request is nonbinding and may
or may not happen." SGI's stl library also says that reserve is "a
request".

What does the standard say about it? I'd be happy to be corrected, but
AFAIK, string's memory is not guaranteed to be contiguous and none of
the member-functions have any complexity guarantees whether reserve is
called or not. In other words reserve is not really guaranteed to do
anything at all for std::string.


From the standard [21.3.3/9]
size_type capacity() const;

Returns: the size of the allocated storage in the string.
I understand this to mean that the string here makes the guarantee that it
will be able to host the number of letters given by capacity().
Best

Kai-Uwe Bux
Feb 13 '06 #14

"Alf P. Steinbach" <al***@start.no> wrote in message
news:45************@individual.net...
The request is non-binding for /reducing/ the capacity. It is binding for
/increasing/ the capacity. After a call to reserve() a call to capacity()
must be equal or greater, and capacity() is "the size of the allocated
storage in the string".


As far as string not being contiguous, is this still true?

Even so, does anyone know of an implementation
where it isn't?
Feb 13 '06 #15
In article <7k********************@weber.videotron.net>,
"Duane Hebert" <sp**@flarn2.com> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:45************@individual.net...
The request is non-binding for /reducing/ the capacity. It is binding for
/increasing/ the capacity. After a call to reserve() a call to capacity()
must be equal or greater, and capacity() is "the size of the allocated
storage in the string".


As far as string not being contiguous, is this still true?

Even so, does anyone know of an implementation
where it isn't?


What about strings that use a reference counted implementation, and then
there is SGI's "rope" class. I personally have a string class that uses
a deque as its representation (the interface is still incomplete though.)

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 13 '06 #16
Daniel T. wrote:
In article <wo********************@giganews.com>,
Pete Becker <pe********@acm.org> wrote:

Daniel T. wrote:
"reserve" is a request and nothing more, don't
bother.

After a call to reserve, capacity() must be at least as large as the
argument in the call.

class string {
public:
void reserve( int ) { }
size_type capacity() const { return max_size(); }
};

You mean like the above? That is all that is required AFAIK.


capacity() returns the size of the allocated storage in the string. That
would not be a valid implementation.

The MSDN Library says this of reserve "The request is nonbinding and may
or may not happen." SGI's stl library also says that reserve is "a
request".
The MSDN library says: "Sets the capacity of the string to a number at
least as great as a specified number." That's a little sloppy, because
the specified number is the argument. It does, later, say "The request
is nonbindinag and may or may not happen." But that's right after
"Unlike vector, the member function reserve may be called to shrink the
capacity of an object."

What does the standard say about it?
It says that after the call, capacity is at least as large as the
argument to reserve.
I'd be happy to be corrected, but
AFAIK, string's memory is not guaranteed to be contiguous
That has nothing to do with the string's capacity.
and none of
the member-functions have any complexity guarantees whether reserve is
called or not. In other words reserve is not really guaranteed to do
anything at all for std::string.


Reserve sets capacity. Complexity guarantees are not affected by capacity.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Feb 13 '06 #17
Metaosp wrote:

In this example reserve() is indeed unnecessary, but I actually use
std::string to store a rather large binary data with predetermined size,
I think it would be a good idea to give std::string a hint to avoid
unnecessary reallocating.


It's more than a hint. It will do what you want.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Feb 13 '06 #18
In message <7k********************@weber.videotron.net>, Duane Hebert
<sp**@flarn2.com> writes

"Alf P. Steinbach" <al***@start.no> wrote in message
news:45************@individual.net...
The request is non-binding for /reducing/ the capacity. It is binding for
/increasing/ the capacity. After a call to reserve() a call to capacity()
must be equal or greater, and capacity() is "the size of the allocated
storage in the string".
As far as string not being contiguous, is this still true?


Given that operator[] is defined in terms of data(), is it actually
possible to write a conformant program that could determine the
difference? Or have later revisions of the standard changed the wording
of 21.3.4?

Even so, does anyone know of an implementation
where it isn't?


--
Richard Herring
Feb 13 '06 #19
[for comp.std.c++: this started out regarding 'resize', and developed
into discussing 'reserve']

* Daniel T.:
* Duane Hebert:
* Alf P. Steinbach:

The [reserve] request is non-binding for /reducing/ the capacity.
It is binding for /increasing/ the capacity. After a call to
reserve() a call to capacity() must be equal or greater,
and capacity() is "the size of the allocated storage in the
string".


As far as string not being contiguous, is this still true?

Even so, does anyone know of an implementation where it isn't?


What about strings that use a reference counted implementation, and then
there is SGI's "rope" class. I personally have a string class that uses
a deque as its representation (the interface is still incomplete though.)


A reasonable interpretation of the standard's text, quoted above, is
that if s has capacity n then assignment of a string of n characters to
s will not fail -- it would have been nice if that was stated
explicitly, but then the standard isn't even clear on what a region of
storage is (at least one committee member thinks it means any number of
scattered small regions), presumably to provide leeway for compilers.

I.e. the natural interpretation, as I see it, is that the storage
referred to is not the storage in some way owned by the string instance,
for that would be meaningless, but is the storage guaranteed to be
available for storing characters, for this instance.

How that is accomplished only affects the operational efficiency in
various contexts, not what can be assumed about success of operations.
I've taken the liberty of multi-posting this to [comp.std.c++], that is,
a separate posting of the same message to that group. I hope. If
Thunderbird does what I think it will do.

I.e., language lawyer level discussion in csc++, slow mode, and
practical aspects (if any remain to be discussed) in clc++, fast mode.
[Grumble: Thunderbird messes up editing of quoted text with invisible
modes, refusing to do what I want, and inserting spaces in the final
result, invisible while editing. Has some Outlook Express programmer
infiltrated the Mozilla team? Otherwise excellent Thunderbird...
Anyway, if the quoted text is messed up, that's why. Looks fine here.]

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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

Feb 13 '06 #20
On Mon, 13 Feb 2006 11:52:02 +0800, Metaosp <me*****@gmail.com> wrote:
In this example reserve() is indeed unnecessary, but I actually use
std::string to store a rather large binary data with predetermined size,
I think it would be a good idea to give std::string a hint to avoid
unnecessary reallocating.


This is not always the case, unfortunately. Consider:

void foo (const string& str) {
string buf;
buf.reserve (str.size() + 1);
buf.assign (str);
buf.append (1, 'X');
// ...
}

The above code is totally inefficient when string uses a ref-counted
implementation. The reserved space is deallocated immediately by
assign() because of ref-counting; append() possibly triggers a
reallocation again.
If you heavily use string you must either program against your current
std::string implementation and hope that your library vendor does not
change it (Microsoft did) or alternatively use another (your own)
string class. In the latter case it's probably better to split the
string functionality into more than one class (see String and
StringBuilder in Java and C#).

Best wishes,
Roland Pibinger
Feb 13 '06 #21
BobR wrote:
Larry I Smith wrote in message ...
metaosp wrote:
Hi, in the following code:
string foo("foo");
foo.resize(10);
foo.append("bar");
cout << foo << endl; // output is "foo"
I expect the output to be "foobar", although "bar" is also
understandable if resize() reset the string. But "foo"? Where does
"bar" go?
Thanks,
Metaosp Delete the "foo.resize(10);" line.
It is not necessary, ***and it appends nul bytes ('\0')***
to the end of "foo" to make the total size 10.


Not if you give it something else: foo.resize( 10, ' ' );


Yes, that's true, but we weren't talking about the 2 arg
resize() were we?

[snip]
--
Bob R
POVrookie


Regards,
Larry
Feb 14 '06 #22
Daniel T. wrote:
In article <7k********************@weber.videotron.net>,
"Duane Hebert" <sp**@flarn2.com> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:45************@individual.net...
> The request is non-binding for /reducing/ the capacity. It is binding
> for
> /increasing/ the capacity. After a call to reserve() a call to
> capacity() must be equal or greater, and capacity() is "the size of the
> allocated storage in the string".
As far as string not being contiguous, is this still true?

Even so, does anyone know of an implementation
where it isn't?


What about strings that use a reference counted implementation,


those can be done with contiguous memory.

and then there is SGI's "rope" class.
That does not implement the interface of std::string, if I recall correctly.
At least, things like capacity() are faked and will lie to yo.

I personally have a string class that uses
a deque as its representation (the interface is still incomplete though.)


A tricky part is the data() member function. If you need to implement that,
you may as well go for a vector based implementation in the first place.
Best

Kai-Uwe Bux

Feb 14 '06 #23
In article <ds**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
Daniel T. wrote:
In article <7k********************@weber.videotron.net>,
"Duane Hebert" <sp**@flarn2.com> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:45************@individual.net...

> The request is non-binding for /reducing/ the capacity. It is binding
> for
> /increasing/ the capacity. After a call to reserve() a call to
> capacity() must be equal or greater, and capacity() is "the size of the
> allocated storage in the string".

As far as string not being contiguous, is this still true?

Even so, does anyone know of an implementation
where it isn't?


What about strings that use a reference counted implementation,


those can be done with contiguous memory.


As I said, however things can get tricky if two different strings want
the rep to be two different sizes... I guess that's why resize to
something smaller won't always work...
and then there is SGI's "rope" class.


That does not implement the interface of std::string, if I recall correctly.
At least, things like capacity() are faked and will lie to yo.


Well, that's the question isn't it, how would you as a user of the class
know?
I personally have a string class that uses
a deque as its representation (the interface is still incomplete though.)


A tricky part is the data() member function. If you need to implement that,
you may as well go for a vector based implementation in the first place.


And by extension the "c_str()" member-function. They can both be
implemented by temporarily creating a block of memory, and filling it
from the representation. That block can be deleted as soon as a
non-const member-function is called. Is this wasteful and slow? Yes, for
large strings it is, but AFAIC, "data()" and "c_str()" mainly exist so
that 'c' code can be called with a string from 'c++'.

So, the real point is to not need to call 'c_str()' or 'data()' on large
strings... I believe the fstream library is the only standard C++ code
that *can't* use strings...
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 14 '06 #24

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.