vector::resize() and memory allocation

Discussion in 'C++' started by Alex Vinokur, Aug 2, 2004.

  1. Alex Vinokur

    Alex Vinokur Guest

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


    --
    Alex Vinokur
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Aug 2, 2004
    #1
    1. Advertising

  2. Alex Vinokur wrote:
    > ---------
    > #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
    Victor Bazarov, Aug 2, 2004
    #2
    1. Advertising

  3. Alex Vinokur

    Alex Vinokur Guest

    "Victor Bazarov" <> wrote in message news:u7tPc.353$09.us.to.verio.net...
    > Alex Vinokur wrote:
    > > ---------
    > > #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;
    }
    ---------


    --
    Alex Vinokur
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Aug 2, 2004
    #3
  4. Alex Vinokur

    Pete Becker Guest

    Victor Bazarov wrote:
    >
    > 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.

    --

    Pete Becker
    Dinkumware, Ltd. (http://www.dinkumware.com)
    Pete Becker, Aug 2, 2004
    #4
  5. Pete Becker wrote:
    > Victor Bazarov wrote:
    >
    >>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.


    What would the result of such compilation be? Undefined?
    Victor Bazarov, Aug 2, 2004
    #5
  6. "Alex Vinokur" <> wrote in message
    news:...

    > 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.
    Andrew Koenig, Aug 2, 2004
    #6
  7. Alex Vinokur

    Alex Vinokur Guest

    "Pete Becker" <> wrote in message news:...
    > Victor Bazarov wrote:
    > >
    > > 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.
    >
    > --
    >
    > Pete Becker
    > Dinkumware, Ltd. (http://www.dinkumware.com)



    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)

    -------------------------

    --
    Alex Vinokur
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Aug 2, 2004
    #7
  8. Alex Vinokur

    Pete Becker Guest

    Victor Bazarov wrote:
    >
    > Pete Becker wrote:
    > > Victor Bazarov wrote:
    > >
    > >>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.

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

    --

    Pete Becker
    Dinkumware, Ltd. (http://www.dinkumware.com)
    Pete Becker, Aug 2, 2004
    #8
  9. Alex Vinokur

    Pete Becker Guest

    Alex Vinokur wrote:
    >
    > "Pete Becker" <> wrote in message news:...
    > > Victor Bazarov wrote:
    > > >
    > > > 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.
    > >
    > > --
    > >
    > > Pete Becker
    > > Dinkumware, Ltd. (http://www.dinkumware.com)

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

    --

    Pete Becker
    Dinkumware, Ltd. (http://www.dinkumware.com)
    Pete Becker, Aug 2, 2004
    #9
  10. Alex Vinokur

    Alex Vinokur Guest

    "Andrew Koenig" <> wrote in message news:ertPc.165649$...
    >
    > "Alex Vinokur" <> wrote in message
    > news:...
    >
    > > 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

    -------------------------------


    --
    Alex Vinokur
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Aug 3, 2004
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ken
    Replies:
    24
    Views:
    3,834
    Ben Bacarisse
    Nov 30, 2006
  2. chris
    Replies:
    6
    Views:
    971
    chris
    Oct 28, 2005
  3. Jason Heyes
    Replies:
    8
    Views:
    708
    Andrew Koenig
    Jan 15, 2006
  4. Replies:
    8
    Views:
    1,891
    Csaba
    Feb 18, 2006
  5. hapa
    Replies:
    4
    Views:
    1,014
    Juha Nieminen
    Aug 23, 2010
Loading...

Share This Page