Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulating new[] with argument constructor

If I am not modifying any static variable inside the argument constructor, is below the proper way to simulate new T[N] (x,y); (array new with arguments) ?

template<typename T>
void* operator new [] (size_t size, const T &value)
{
  T* p = (T*) malloc(size);
  for(int i = size / sizeof(T) - 1; i >= 0; i--)
    memcpy(p + i, &value, sizeof(T));
  return p;
}

Usage will be,

struct A
{
  A () {}  // default
  A (int i, int j) {} // with arguments
};

int main ()
{
  A *p = new(A(1,2)) A[10];  // instead of new A[10](1,2)
}
like image 605
iammilind Avatar asked May 20 '11 09:05

iammilind


2 Answers

I'd suggest

 std::vector<A> v(10, A(1,2));

I realize that this doesn't really address the question for arrays. You could use

 p = &v[0]; 

since the standard guarantees contiguous storage. Be very careful with resizing the vector though, because it could invalidate p

I checked boost::array<> (which adapts C style arrays), but it doesn't define constructors...

like image 84
sehe Avatar answered Oct 19 '22 13:10

sehe


This isn’t OK. You are copying objects into uninitialised memory without invoking proper copy semantics.

As long as you’re only working with PODs, this is fine. However, when working with objects that are not PODs (such as your A) you need to take precautions.

Apart from that, operator new cannot be used in this way. As Alexandre has pointed out in the comments, the array won’t be initialised properly since C++ will call constructors for all elements after having called your operator new, thus overriding the values:

#include <cstdlib>
#include <iostream>

template<typename T>
void* operator new [] (size_t size, T value) {
    T* p = (T*) std::malloc(size);
    for(int i = size / sizeof(T) - 1; i >= 0; i--)
        new(p + i) T(value);
    return p;
}

struct A {
    int x;
    A(int x) : x(x) { std::cout << "int ctor\n"; }
    A() : x(0) { std::cout << "default ctor\n"; }
    A(const A& other) : x(other.x) { std::cout << "copy ctor\n"; }
};

int main() {
    A *p = new(A(42)) A[2];
    for (unsigned i = 0; i < 2; ++i)
        std::cout << p[i].x << std::endl;
}

This yields:

int ctor
copy ctor
copy ctor
default ctor
default ctor
0
0

… not the desired outcome.

like image 30
3 revs Avatar answered Oct 19 '22 14:10

3 revs