3

I can create a function object to create a 100 byte block on the heap using malloc:

auto fn = std::bind(malloc, 100);

But what is the equivalent using new char[]? I realize I can bind to a function or lambda that returns new char[100] but I'd like to understand the syntax for binding to new char[] directly.

Is it even possible, or is new char[] an operator rather than a function and therefore cannot be bound?

Thanks, Craig

cdmh
  • 3,167
  • 1
  • 21
  • 40
  • 1
    Yes, at least as you're using it, `new` is an operator. See: http://stackoverflow.com/a/1885897/179910 for more details. – Jerry Coffin May 15 '13 at 14:56
  • auto x = std::bind(operator new[], 100); ...but no – Exceptyon May 15 '13 at 15:00
  • `auto fn = [](){return new char[];};` Seems to work – rcapote May 15 '13 at 15:07
  • 1
    @rcapote that's a lambda! ;) – cdmh May 15 '13 at 15:07
  • `new char[]` is a call to an operator, which calls _several_ functions. `void* ::operator new(size_t)` and then "the default constructor" for each `char` object. (In truth, that's skipped in this case for obvious reasons). It also stores the number of elements in some unspecified location. – Mooing Duck May 15 '13 at 17:00

2 Answers2

0

Is this what you are looking for?

auto fn = bind<void*>(operator new[], sizeof(char)*100);

auto field = (char*)fn();
tzwickl
  • 1,183
  • 1
  • 12
  • 28
  • (1) [That doesn't compile](http://coliru.stacked-crooked.com/view?id=38361e5d056b11f72c6f4dfeef060c12-50d9cfc8a1d350e7409e81e87c2653ba) (2), `new char[]` is more than just a call to `operator new[]`, even for `char` types. – Mooing Duck May 15 '13 at 17:02
  • @MooingDuck You must include the header file `iostream` because there is the `operator new[]` declared. – tzwickl May 15 '13 at 17:58
  • @MooingDuck I just debugged the following instruction: `int *test = new int[20];` and it calls exactly the same `operator new[]` method defined in `newaop.cpp`. It's just an evaluation of the type that you use, multiplied by the number in the square bracket. `void *__CRTDECL operator new[](size_t count) { return (operator new(count)); }` In my instance the variable `count` was 80 => 20 * int = 20 * 4 Byte – tzwickl May 15 '13 at 18:04
  • half right. I checked, `::operator new` is defined in the `` header, not `` like I thought. However, `operator new[]` isn't bindable like that because it's overloaded. The best I could do was [this](http://ideone.com/tNmwQi) – Mooing Duck May 15 '13 at 18:06
  • I never claimed that `new int[20]` didn't call `void* ::operator new[](size_t)`, what I said that that function is only the _first of many things_ that the `new` operator does. – Mooing Duck May 15 '13 at 18:08
  • @MooingDuck Yes but the `new` operator works completely independent on which type you are using. It always calls the same functions because the `new` operator works internally with the type `void`. It's strange why this code doesn't run with your compiler. I use Visual Studio 2012 and it works just like I have expected. – tzwickl May 15 '13 at 18:20
  • http://ideone.com/vJq3qO In this case, I would guess Visual Studio is "cheating" the official rules to guess what you want and compile it. They also do this with templates a lot. To be fair, GCC cheats with runtime sized automatic arrays, so it's not just one compiler. – Mooing Duck May 15 '13 at 18:24
0

If you just want space, you're correct that can simply bind ::operator new, but in the general case, new T[] does more. Unfortunately, ::operator new is overloaded, so the compiler doesn't know which one you want, so you have to "cast" it to get the right overload. tom1991t says MSVC compiles it without the cast, but I don't think the compiler is supposed to do that.

#include <functional>
#include <new>

int main() {
    typedef void*(*newptr_type)(std::size_t);  
    typedef void(*delptr_type)(void*);        
    auto al = std::bind<void*>(newptr_type(::operator new), sizeof(char)*100);   
    auto dl = delptr_type(::operator delete);   

    auto field = (char*)al();
    dl(field); //or just "delete[] field;"
}

Note that this is not the same as new T[] in the general case, since this doesn't construct nor would the inverse ::operator delete call any destructors, but for char we don't care.

Some compilers refuse to inline function pointers under any conditions, so a functionoid would be better, including a lambda (As suggested by rcapote). This solution could handle constructors and destructors, and should run faster due to inlining.

auto al = [](){return new char[100];};
auto dl = [](char* p){delete[] p;};

auto field = (char*)al();
dl(field); //or just "delete[] field;"

Proof of compilation

Community
  • 1
  • 1
Mooing Duck
  • 56,371
  • 16
  • 89
  • 146