vector::resize() and memory allocation

A

Alex Vinokur

---------
#include <vector>
using namespace std;
struct Foo
{
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
 
V

Victor Bazarov

Alex said:
---------
#include <vector>
using namespace std;
struct Foo
{
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
---------

For how many Foo instances is memory allocated at "Check point"?
It seems that for 2 insistences?
If it is truth does it mean that use of vector::resize() involves allocating extra memory?

The program is ill-formed because 'Foo' does not fit the requirement
"Default-constructible" needed for the call to 'resize'. It should
not compile.

Now, if you just missed that thing, and actually didn't mean to ask
a trick question (and supposedly 'Foo' actually has a default c-tor),
then it is unspecified how many objects 'v1' can actually contain
after you asked to resize it because the initial capacity of it is 0
and 'resize' _will_ cause reallocation to accommodate your object.
To what size the allocation happens is unspecified (implementation-
defined, I believe).

So, after 'Foo' is given a default c-tor, the answer to your first
question is "unknown" or "implementation-defined", the answer to your
second question is "I don't understand", and the answer to your third
question is "yes, possibly".

Victor
 
A

Alex Vinokur

Victor Bazarov said:
Alex said:
---------
#include <vector>
using namespace std;
struct Foo
{
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
---------

For how many Foo instances is memory allocated at "Check point"?
It seems that for 2 insistences?
If it is truth does it mean that use of vector::resize() involves allocating extra memory?

The program is ill-formed because 'Foo' does not fit the requirement
"Default-constructible" needed for the call to 'resize'. It should
not compile.
[snip]

To simplify the program I removed "Foo() {}" by mistake.

Here is the updated program.
---------
#include <vector>
using namespace std;
struct Foo
{
Foo () {}
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
 
P

Pete Becker

Victor said:
The program is ill-formed because 'Foo' does not fit the requirement
"Default-constructible" needed for the call to 'resize'. It should
not compile.

The compiler should issue a diagnostic. There is no requirement that it
not compile the code.
 
V

Victor Bazarov

Pete said:
The compiler should issue a diagnostic. There is no requirement that it
not compile the code.

What would the result of such compilation be? Undefined?
 
A

Andrew Koenig

Here is the updated program.
---------
#include <vector>
using namespace std;
struct Foo
{
Foo () {}
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
---------

At "Check point", one Foo object exists, namely v1[0].
That object was created by the call to resize, and then overwritten by
assignment from the Foo(100) object, which was then destroyed.
 
A

Alex Vinokur

Pete Becker said:
The compiler should issue a diagnostic. There is no requirement that it
not compile the code.


g++ doesn't compile this code.

------ foo.cpp ------
#include <vector>
using namespace std;

struct Foo
{
Foo (int) {}
};

int main ()
{
vector<Foo> v;
v.resize(1);
v[0] = Foo (100);
return 0;
}
---------------------


------ Compilation ------

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[---omitted---]

$ g++ foo.cpp
/usr/include/c++/3.3.1/bits/stl_vector.h: In member function `void
std::vector<_Tp, _Alloc>::resize(unsigned int) [with _Tp = Foo, _Alloc =
std::allocator<Foo>]':
foo.cpp:12: instantiated from here
/usr/include/c++/3.3.1/bits/stl_vector.h:452: error: no matching function for
call to `Foo::Foo()'
foo.cpp:5: error: candidates are: Foo::Foo(const Foo&)
foo.cpp:6: error: Foo::Foo(int)
 
P

Pete Becker

Victor said:
What would the result of such compilation be? Undefined?

Up to the implementor. It has nothing to do with the standard's notion
of undefined behavior.

Let's back up a bit -- this is a common area for confusion:

The standard says that compilers that claim to conform to the standard
must compile well-formed programs, and it specifies what the behavior of
such programs is. That behavior isn't necessarily unique, because some
aspects of the language are implementation-defined (such a construct is
valid, and the implementation must document what it does -- for example,
whether char is signed or unsigned is implementation-defined, so testing
whether a char value is less than zero might always yield false) and
some are unspecified (such a construct is valid, but the implementation
is not required to document what it does -- for example, the order of
evaluation of function arguments is unspecified).

Then there are programs that are ill-formed, that is, they violate the
rules that the standard lays down for well-formed programs. For some of
these rules the behavior is simply undefined: the compiler can do
anything, and isn't required to tell you what it did or even that you
broke the rules (i=i++, for example). For most of the rules a diagnostic
is required. Having given a diagnostic, the compiler has told you that
the rules for standard C++ no longer apply; it is then free to do
anything, without violating the standard. That's the hook for conforming
extensions -- take something that's otherwise invalid and do something
meaningful with it. Microsoft's __declspec stuff, and GNU's
__attribute__ stuff, are examples of this: they occur in places where
such things aren't allowed, so the compiler is required to issue a
diagnostic; after doing this, these compilers change how they compile
the surrounding code (you don't usually see these warnings because you
run the compiler in a mode that disables them).

In the example at hand there's no obvious sensible extension behavior,
so chances are the result will actually be a refusal to compile the
code. But that's not because the standard requires it.
 
P

Pete Becker

Alex said:
g++ doesn't compile this code.

I don't know of a compiler that will compile that code. Nevertheless,
the standard doesn't require that compilers not compile it. All it
requires is that they issue a diagnostic.
 
A

Alex Vinokur

Andrew Koenig said:
Here is the updated program.
---------
#include <vector>
using namespace std;
struct Foo
{
Foo () {}
Foo (int) {}
};
int main ()
{
vector<Foo> v1;
v1.resize(1);
v1[0] = Foo (100);
// Check point
return 0;
}
---------

At "Check point", one Foo object exists, namely v1[0].
That object was created by the call to resize, and then overwritten by
assignment from the Foo(100) object, which was then destroyed.

You are right (See Check-point-3).

------ foo.cpp ------

#include <vector>
#include <iostream>
using namespace std;

struct Foo
{
static int ctors_s;
static int dtors_s;

Foo () { ctors_s++; cout << "Ctor()" << endl; }
Foo (const Foo&) { ctors_s++; cout << "Copy Ctor()" << endl; }
Foo (int) { ctors_s++; cout << "Ctor(int)" << endl; }
~Foo () { dtors_s++; cout << "Dtor" << endl; }
};
int Foo::ctors_s(0);
int Foo::dtors_s(0);


#define SHOW_IT(x) cout << x << " : capacity = " << v.capacity() \
<< ", vector size = " << v.size() \
<< ", alive instances = " << (Foo::ctors_s - Foo::dtors_s) \
<< endl << endl

int main ()
{
vector<Foo> v;
SHOW_IT("Check-point-1");

v.resize(1);
SHOW_IT("Check-point-2");

v[0] = Foo (100);
SHOW_IT("Check-point-3");

v.reserve(5);
SHOW_IT("Check-point-4");

return 0;
}
---------------------


------ Compilation & Run ------

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[---omitted---]

$ g++ foo.cpp


$ a

Check-point-1 : capacity = 0, vector size = 0, alive instances = 0

Ctor()
Copy Ctor()
Dtor
Check-point-2 : capacity = 1, vector size = 1, alive instances = 1

Ctor(int)
Dtor
Check-point-3 : capacity = 1, vector size = 1, alive instances = 1

Copy Ctor()
Dtor
Check-point-4 : capacity = 5, vector size = 1, alive instances = 1

Dtor
 

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,009
Latest member
GidgetGamb

Latest Threads

Top