problem with string::resize

M

metaosp

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
 
B

Bo Persson

metaosp said:
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
 
L

Larry I Smith

metaosp said:
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
 
M

metaosp

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
 
D

Daniel T.

metaosp said:
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.
 
D

Duane Hebert

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?
 
B

BobR

Larry I Smith wrote in message ...
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
 
P

Pete Becker

Daniel said:
"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.
 
D

Daniel T.

"Duane Hebert said:
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 said:
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.
 
M

Metaosp

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,
 
D

Daniel T.

Metaosp said:
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.
 
D

Daniel T.

Pete Becker said:
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.
 
K

Kai-Uwe Bux

Daniel said:
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
 
A

Alf P. Steinbach

* Daniel T.:
* Pete Becker:

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".
 
D

Duane Hebert

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?
 
D

Daniel T.

"Duane Hebert said:
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.)
 
P

Pete Becker

Daniel said:
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.
 
P

Pete Becker

Metaosp said:
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.
 
R

Richard Herring

Duane Hebert said:
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?
 
A

Alf P. Steinbach

[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.]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top