You can't have objects that didn't have their constructor called in a valid program. At some point you'll need to call the constructor, before you actually use the instance, and that is what placement new is for.
Here's an example of such a class:
Code:
#include <iostream>
#include <cassert>
#include <string>
#include <algorithm>
#include <iterator>
template <class T, unsigned Size>
class Array
{
char buffer[Size * sizeof(T)];
unsigned count;
public:
Array(): count(0) {}
//also needed: copy constructor, assignment operator and destructor
unsigned size() const { return count; }
unsigned capacity() const { return Size; }
void push_back(const T& value)
{
assert(size() < capacity());
new (to_object(size())) T(value);
++count;
}
void pop_back()
{
assert(size() > 0);
--count;
to_object(size())->~T();
}
typedef const T* const_iterator;
typedef T* iterator;
typedef T value_type;
typedef const T& const_reference;
iterator begin() { return to_object(0); }
iterator end() { return to_object(size()); }
const_iterator begin() const { return to_object(0); }
const_iterator end() const { return to_object(size()); }
private:
const T* to_object(unsigned index) const
{
return reinterpret_cast<T*>(buffer) + index;
}
T* to_object(unsigned index)
{
return reinterpret_cast<T*>(buffer) + index;
}
};
int main()
{
std::string data[] = {"The", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"};
const unsigned size = sizeof(data) / sizeof(data[0]);
Array<std::string, size> array;
std::copy(data, data + size, std::back_inserter(array));
std::copy(array.begin(), array.end(), std::ostream_iterator<std::string>(std::cout, " "));
while (array.size() > 0) {
std::cout << '\n' << array.size();
array.pop_back();
}
}