Understanding placement new

Ok so I can't seem to find really anything useful of placement new. I have this example: (variable naming here is super useful \sarcasm)
1
2
3
4
5
void construct(T * const p, const T& t) const {
        void * const pv = static_cast<void *>(p);
 
        new (pv) T(t);
    }

From: http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-mallocator.aspx?Redirected=true

I don't understand what this function is really doing. I can see pv is a void pointer with the address that p has (I think), and then the second line constructs an object T at address pv, using the copy constructor?
maybe you'll find this link more useful:

http://www.parashift.com/c++-faq/placement-new.html

EDIT:

I can see pv is a void pointer with the address that p has (I think), and then the second line constructs an object T at address pv, using the copy constructor?


Your understanding is correct.
Last edited on
So, doing this I get rid of the requirement of a default constructor, but then I'm requiring a copy constructor be defined?
Here's some example code that may aid the understanding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <cstddef>
#include <new>
#include <iostream>

template <typename T>
class Vector
{
public:
    Vector( std::size_t n, const T& t ) ; 
    ~Vector() ;

private:
    std::size_t _capacity ;
    std::size_t _size ;
    T* _data ;
};

template <typename T>
Vector<T>::Vector( std::size_t n, const T& t )
    : _capacity(n), _size(0), 
      _data(reinterpret_cast<T*>(operator new(sizeof(T)*n)))
{
    try {
        while ( _size < _capacity )
        {
            new (_data+_size) T(t) ;
            ++_size ;
        }
    }
    catch( ... )
    {
        while (_size > 0 )
            _data[--_size].~T() ;

        operator delete(_data) ;
        throw ;
    }
}

template <typename T>
Vector<T>::~Vector()
{
    T* begin = _data ;
    T* end = _data+_size ;

    while ( --end >= begin )
        end->~T() ;

    operator delete(_data) ;
}

class A
{
public:
    A(int) { std::cout << "A(int)\n" ;}
    A(const A&) { std::cout << "A(const A&)\n"; }
    ~A() { std::cout << "~A()\n"; }
};

int main()
{
    Vector<A> v(5, A(5)) ;
}
A(int)
A(const A&)
A(const A&)
A(const A&)
A(const A&)
A(const A&)
~A()
~A()
~A()
~A()
~A()
~A()


I believe everything is correct there, but manual memory management can be tricky. I would say you may get rid of the default constructor requirement for certain uses (as oopposed to getting rid of the requirement altogether), such as the constructor illustrated here. However, if you want to use std::vector::resize functionality, obviously that cannot be done without a default constructor. Whether or not the requirement to use an element's default constructor is in place for this Vector constructor, the copy constructor is also required -- so you're not exchanging one requirement for another.
Last edited on
Placement new doesn't require a copy constructor. You can use any constructor. It's the whole point of placement new.
Last edited on
Ok so I can't seem to find really anything useful of placement new.
I think memory pools use placement new.
He meant he couldn't find any useful information in placement new, not that he couldn't find an issue for it. The reason he is looking up placement new was because I told him he needed to use it for his vector class (and he does).
Last edited on
Well, I think I need to use in my allocation class. I'd prefer to keep memory allocation separate from the vector class, and have it handled by an allocation class. This way when I get on to making the rest of the common data structures I can just reuse the same allocation interface, I think. Not sure how I'll work that out for non-contiguous structures.
Topic archived. No new replies allowed.