Calling container constructor explicitly

Discussion in 'C++' started by daveb, Jul 16, 2006.

  1. daveb

    daveb Guest

    I'm trying to write some code that calls the constructors of STL
    containers explicitly, and I can't get it to compile. A sample program
    is below. One compiler complains about the last two lines (the map
    constructor calls), saying that I'm trying to take the address of a
    constructor. Another compiler complains about all four of the last
    lines, just saying "invalid use of class". What is the correct syntax
    for calling a container constructor explicitly?

    You're probably wondering why I'm not calling "new" instead of malloc
    and the constructor. It's because what I really need to do is to call
    a proprietary memory allocation function (i.e., not malloc) and then
    call a parameterized constructor on the returned space. So neither
    "new" nor "placement new" will work for me.

    Thanks for the help!

    - Dave


    #include <vector>
    #include <map>
    #include <cstdlib>

    int
    main()
    {
    typedef std::vector<int> VecType;
    typedef std::map<int, int> MapType;

    VecType v, *vp;
    MapType m, *mp;

    vp = (VecType *)malloc(sizeof(VecType));
    mp = (MapType *)malloc(sizeof(MapType));

    // call constructors
    v.VecType::vector();
    vp->VecType::vector();
    m.MapType::map();
    mp->MapType::map();
    }
    daveb, Jul 16, 2006
    #1
    1. Advertising

  2. * daveb:
    > I'm trying to write some code that calls the constructors of STL
    > containers explicitly, and I can't get it to compile.


    The following is an implicit constructor call ("implicit" means "implied
    or understood though not directly expressed"):

    std::vector<int> v;

    The following is an explicit constructor call ("explicit" means "fully
    and clearly expressed; leaving nothing implied"):

    std::vector<int>();

    The last one creates a temporary; see the FAQ.


    > A sample program
    > is below. One compiler complains about the last two lines (the map
    > constructor calls), saying that I'm trying to take the address of a
    > constructor. Another compiler complains about all four of the last
    > lines, just saying "invalid use of class". What is the correct syntax
    > for calling a container constructor explicitly?


    In general, supplying a constructor argument list after a type
    specification is the correct syntax for calling a constructor
    explicitly. But that's not a formal view: it's just a summary of the
    effect of the formal syntax rules. Also, note that the opposite does
    not hold: int() constructs the int value 0, but int has no constructor.


    > You're probably wondering why I'm not calling "new" instead of malloc
    > and the constructor. It's because what I really need to do is to call
    > a proprietary memory allocation function (i.e., not malloc) and then
    > call a parameterized constructor on the returned space. So neither
    > "new" nor "placement new" will work for me.


    Placement new is exactly for that.

    But it's a rather silly thing, nay, STRONGERWORD thing, to do.

    A vector object by itself takes up just a few bytes. The contents are
    typically allocated separately. To take charge of the allocation for
    vector contents you need to specify an allocator type in the type
    definition.


    > #include <vector>
    > #include <map>
    > #include <cstdlib>
    >
    > int
    > main()
    > {
    > typedef std::vector<int> VecType;
    > typedef std::map<int, int> MapType;
    >
    > VecType v, *vp;


    At this point v has been constructed and vp is uninitialized pointer.


    > MapType m, *mp;
    >
    > vp = (VecType *)malloc(sizeof(VecType));
    > mp = (MapType *)malloc(sizeof(MapType));
    >
    > // call constructors
    > v.VecType::vector();
    > vp->VecType::vector();


    Syntax error.

    The way to call constructors on raw storage is to use placement new, but
    see above: it's STRONGERWORD for std::vector, check out allocators.


    --
    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?
    Alf P. Steinbach, Jul 16, 2006
    #2
    1. Advertising

  3. daveb wrote:

    > What is the correct syntax for calling a container constructor explicitly?


    The same as for any other class: none.

    > You're probably wondering why I'm not calling "new" instead of malloc
    > and the constructor. It's because what I really need to do is to call
    > a proprietary memory allocation function (i.e., not malloc) and then
    > call a parameterized constructor on the returned space. So neither
    > "new" nor "placement new" will work for me.


    Strange. "placement new" is habitually used for that.

    If you want that the contained objects, not the container object itself, use
    your allocation function, write an adequate allocator and use it.

    --
    Salu2
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jul 16, 2006
    #3
  4. daveb

    Kai-Uwe Bux Guest

    daveb wrote:

    > I'm trying to write some code that calls the constructors of STL
    > containers explicitly, and I can't get it to compile. A sample program
    > is below. One compiler complains about the last two lines (the map
    > constructor calls), saying that I'm trying to take the address of a
    > constructor. Another compiler complains about all four of the last
    > lines, just saying "invalid use of class". What is the correct syntax
    > for calling a container constructor explicitly?


    That depends on what you mean by calling the constructor explictly. The
    standard reserves this language for the function notation of a type
    conversion like

    std::string( "hello world" );

    Despite that, placement new is what is semantically closest to calling a
    constructor.

    > You're probably wondering why I'm not calling "new" instead of malloc
    > and the constructor. It's because what I really need to do is to call
    > a proprietary memory allocation function (i.e., not malloc) and then
    > call a parameterized constructor on the returned space. So neither
    > "new" nor "placement new" will work for me.


    Huh? Isn't this exactly what placement new is doing: construct an object at
    a specified location in memory by invoking the constructor appropriate for
    the given arguments?

    >
    > Thanks for the help!
    >
    > - Dave
    >
    >
    > #include <vector>
    > #include <map>
    > #include <cstdlib>
    >
    > int
    > main()
    > {
    > typedef std::vector<int> VecType;
    > typedef std::map<int, int> MapType;
    >
    > VecType v, *vp;
    > MapType m, *mp;
    >
    > vp = (VecType *)malloc(sizeof(VecType));
    > mp = (MapType *)malloc(sizeof(MapType));
    >
    > // call constructors
    > v.VecType::vector();
    > vp->VecType::vector();
    > m.MapType::map();
    > mp->MapType::map();
    > }



    That won't fly as constructors don't have names, are not found by name
    lookup and therefore cannot be called like member functions.

    What about:

    VecType v;
    VecType* vp = (VecType *)malloc(sizeof(VecType));
    new ( vp ) VecType ();

    MapType m;
    MapType* mp = (MapType *)malloc(sizeof(MapType));
    new ( mp ) MapType ();


    Best

    Kai-Uwe
    Kai-Uwe Bux, Jul 16, 2006
    #4
  5. daveb

    Ron Natalie Guest

    daveb wrote:

    >
    > You're probably wondering why I'm not calling "new" instead of malloc
    > and the constructor. It's because what I really need to do is to call
    > a proprietary memory allocation function (i.e., not malloc) and then
    > call a parameterized constructor on the returned space. So neither
    > "new" nor "placement new" will work for me.


    I'm not sure why you jump to the conclusion placement new will not
    work. It appears to be exactly what you want.

    You can't call constructors PERIOD. The best you can do is create
    objects with a different allocation function (i.e., placement new).

    You do know that the memory used by a standard container itself
    is tiny compared with the memory for the contained objects which
    you probably need to write an allocation function for as well.
    Ron Natalie, Jul 16, 2006
    #5
  6. daveb

    daveb Guest

    My thanks to everyone who responded. I was under the impression that
    placement new could be used only to call an object's *default*
    constructor. But I infer from the code that Kai-Uwe provided that
    parameterized constructors can be called by providing the parameters
    within parentheses at the end of the statement. If so, (as most of you
    noted) that's exactly what I need.

    BTW, this is embedded firmware. I need the proprietary memory
    allocator because the container and its contents must reside in a
    "persistent" area of memory that is not initialized at boot time. I
    already intended to provide a custom allocator to the container, but
    this custom allocator will be called only for the *contents* of the
    container, correct? I also need the container itself to live in the
    persistent region of memory.

    - Dave
    daveb, Jul 17, 2006
    #6
  7. * Julián Albo:
    > daveb wrote:
    >
    >> What is the correct syntax for calling a container constructor explicitly?

    >
    > The same as for any other class: none.


    Do not perpetuate urban myths, please.

    --
    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?
    Alf P. Steinbach, Jul 17, 2006
    #7
    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. Replies:
    7
    Views:
    525
    Frederick Gotham
    Sep 8, 2006
  2. shsingh
    Replies:
    13
    Views:
    724
  3. Kavya
    Replies:
    3
    Views:
    308
    Frederick Gotham
    Oct 29, 2006
  4. Lawrence Spector
    Replies:
    3
    Views:
    279
    Kai-Uwe Bux
    Jul 16, 2007
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,183
Loading...

Share This Page