사실 저게 왜 다른지를 자세히 설명하자면 ABI 등등해서도 알아둬야할게 좀 있긴 한데 최대한 간단하게 설명하자면


일단 new 표현이랑 operator new()에 대해서 알아둘 필요가 있어.


myclass *ptr = new myclass(); 같은 new expression은 내부적으로 다음과 같이 처리돼.


myclass *ptr = ::operator new(sizeof(myclass)); // 메모리 할당

new (ptr) myclass(); // 생성자 호출


new[]의 경우에는 조금 다른데, myclass *arr = new myclass[n];는 다음처럼 처리돼.


myclass *arr = ::operator new(n * sizeof(myclass)); // 메모리 할당

for(size_t i = 0; i < n; ++i) {

  new (arr + i) myclass(); // 생성자 호출

}


delete ptr도 비슷하게 표현하자면


    if(ptr) {

      ptr->~myclass(); // 소멸자 호출

      ::operator delete(ptr);

    }


여기까지는 그닥 어렵지 않은데, 문제는 delete[]야.


new expression같은 경우에는 객체가 몇개인지가 인자 n으로 넘어오는데, delete[] 같은 경우에는 몇개의 객체를 해제해야하는지 알 수가 없어.


그래서 ABI마다 다르긴 하지만 보통 new[]를 할때, 몇개의 객체를 갖고 있는지에 대한 정보를 담는 cookie를 추가해서 메모리를 할당하곤 해. (http://mentorembedded.github.io/cxx-abi/abi.html#array-cookies 참고)


이렇게 처리하면 myclass *arr = new myclass[n]; 은 다음과 같은 일들을 수행하고


void *ptr = ::operator new(sizeof(size_t) + n * sizeof(myclass)); // 메모리 할당

*static_cast<size_t*>(ptr) = n;

myclass *arr = reinterpet_cast<myclass*>((size_t*)ptr + 1);

for(size_t i = 0; i < n; ++i) {

  new (arr + i) myclass(); // 생성자 호출

}


delete[] arr은 다음과 같은 일들을 수행해


   size_t *ptr = reinterpret_cast<size_t*>(arr) - 1;

   for(size_t i = 0; i < *ptr; ++i) {

     (arr + i)->~myclass(); // 소멸자 호출
   }

   ::operator delete(ptr);


실제로 저 코드대로 똑같이 수행된다는 건 아니고, 대충 저런 과정을 거친다는거야.


진짜로 저런 식으로 되는지 간단하게 확인해보려면 ::operator new랑 ::operator delete을 재정의해보면 확인할 수 있어.


http://ideone.com/9KVUvZ


myclass의 크기가 2이고 3개를 할당하니까 6byte만 할당해야하는데 10바이트가 할당되는걸 볼 수가 있을거야. 객체의 개수를 담을 size_t 만큼의 공간을 더 할당하는거지.



좀 더 추가하자면, array cookie를 붙이는건 모든 객체에 대해 소멸자를 호출해주기 위한 거라서, 소멸자가 trivial할 경우에는 array cookie를 안붙이는게 보통이야. 위에 참고로 링크한 문서에도 'No cookie is required if the array element type T has a trivial destructor' 라고 되어있어.


작동과정을 설명하기 위해서 간단하게 코드로 표현했지만 ABI마다 다를 수 있는 내용이니까 왜 delete와 delete[]를 구분해서 사용해야하는지만 이해하면 될 거야.



요약. new/delete, new[]/delete[] 쌍은 무조건 맞춰줘야한다. delete [] arr+1 이 된다는건 개소리.