WHAT DOES std::unique_ptr<char[]> buf(new char[size]); MEAN

hi everybody
i was just studying example of wifimanager and this line of code came by which i couldn't understand.....could someone please explain me this, what does this mean..

 // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

thanks

I find the syntax ugly (mostly because my C++ isn't up to that level yet), but it looks like it dynamically allocates an array of char's (with 'size' elements) and gives control of that array to a "smart pointer" called buf.

std::unique_ptr is a 'template' class. In this case the template is asked to generate a class that deals with a character array. Because it is a class it has a constructor method and a destructor method. The destructor method gets called when the instance goes out of scope so this is a way to prevent memory leaks by automatically 'deleting' the allocated memory when the variable goes out of scope. Without this the declaration would be:

       char *buf = new char[size];

In that case you would have to explicitly put 'delete buff;' every place where buff goes out of scope (like at 'return' statements and at the end of the enclosing block).

johnwasser:
Because it is a class it has a constructor method and a destructor method. The destructor method gets called when the instance goes out of scope so this is a way to prevent memory leaks by automatically 'deleting' the allocated memory when the variable goes out of scope.

I'm thinking this should read:

Because it is a class it has a constructor method and a destructor method. The destructor method gets called when the instance goes out of scope existence so this is a way to prevent memory leaks by automatically 'deleting' the allocated memory when the variable goes out of scope existence.

An object can go out of scope (but still exist) and then come back in scope later.

std::unique_ptr is a 'template' class. In this case the template is asked to generate a class that deals with a character array. Because it is a class it has a constructor method and a destructor method. The destructor method gets called when the instance goes out of scope so this is a way to prevent memory leaks by automatically 'deleting' the allocated memory when the variable goes out of scope. Without this the declaration would be:
Code: [Select]
char *buf = new char;

In that case you would have to explicitly put 'delete buff;' every place where buff goes out of scope (like at 'return' statements and at the end of the enclosing block).[/quote]
:frowning: :frowning:
thanks for your replies....
but this reply suggests i should go back to c++ all over again.......for c++ for me is in my passive memory...
is there a way to simplify this answer or should i bang my head to c++ again,for this line...
also, what i understand is memory allocation takes place
:frowning: :frowning: :frowning: :confused: :confused:

char *buffer = new char[size] allocates memory for a character array of length "size" on the heap, and it saves a pointer to it in the variable "buffer".
When you no longer need the array, you have to call delete[] buffer. By doing this, you free the memory, so other parts of your code can reuse it.
If you forget to delete the buffer after using it, the memory is still allocated, and no one else can use it. This is called a memory leak. If you do that often enough, there will be no more memory left, it's all filled up with data you're no longer using.

Because programmers often forget to call delete[], smart pointers were introduced. When you assign a pointer to a smart pointer, the smart pointer will automatically delete the pointer when it goes out of scope.

Consider the following functions:

#include <memory>

void good() {
    std::unique_ptr<char[]> p{new char[2]()};
}

void medium() {
    char *p = new char[2]();
    delete[] p;
}

void bad() { // memory leak!
    char *p = new char[2]();
}

And here's what they compile to:

good():
        sub     rsp, 8
        mov     edi, 2
        call    operator new[](unsigned long) ; <-------------------
        xor     edx, edx
        mov     WORD PTR [rax], dx
        mov     rdi, rax
        add     rsp, 8
        jmp     operator delete[](void*) ; <-------------------

medium():
        sub     rsp, 8
        mov     edi, 2
        call    operator new[](unsigned long) ; <-------------------
        xor     edx, edx
        mov     WORD PTR [rax], dx
        mov     rdi, rax
        add     rsp, 8
        jmp     operator delete[](void*) ; <-------------------

bad():
        mov     edi, 2
        jmp     operator new[](unsigned long) ; <-------------------

Ignore the mov, xor, sub and add instructions, just focus on the call and jump instructions.

The medium function is what you would do in old C++: you manually call new and delete.
The bad function only calls new, so the memory is never freed, and you get a memory leak.
The good function uses a smart pointer: as you can see, in the C++ code, only new is called, but if you look at the compiled version, you can see that delete is called at the end of the function! The smart pointer cleans up the memory for you, automatically.

Pieter

thanks Pieter....it helped a lot..
now does this inbuilt function delete the allocated memory at the end of program or when??....actually when does it know when to delete....
thanks again

sabishaw:
thanks Pieter....it helped a lot..
now does this inbuilt function delete the allocated memory at the end of program or when??....actually when does it know when to delete....
thanks again

When the pointer goes out of existence, the memory from the dynamic allocation is returned. I say that verses "out of scope" because (Pieter can correct if I'm wrong) I believe it can go out of scope but sill exist to come back into scope later. Example -- during a function call the local pointer variable will be out of scope but still exist on the stack.

thanks.......i got it

The smart pointer lives on the stack. All variables on the stack are destructed when they go out of scope.

For example:

void example(int param) { // param constructed
  int a; // a constructed
  {
    int b; // b constructed
  } // b destructed
  for (int i = 0; i < 42; ++) { // i constructed
    ;
  } // i destructed
} // a, param destructed

The smart pointer deletes the pointer when it is destructed, so when it goes out of scope.

gfvalvo:
When the pointer goes out of existence the memory from the dynamic allocation is returned. I say that verses "out of scope" because (Pieter can correct if I'm wrong) I believe it can go out of scope but sill exist to come back into scope later.

When it's on the stack, it's always deleted when it goes out of scope, no matter if it's used again later or not.

If the smart pointer is on the heap (why on earth would you do that?), it's deleted when the smart pointer is deleted.

PieterP:
The smart pointer deletes the pointer when it is destructed, so when it goes out of scope.
When it's on the stack, it's always deleted when it goes out of scope, no matter if it's used again later or not.

I respectfully disagree:

void good();
void anotherFunction();  <-------------- Pointer "p" goes out of scope 

void good() {
    std::unique_ptr<char[]> p{new char[2]()};
    anotherFunction();    
    // <---- Pointer "p" is back in scope. It wasn't deleted for the function call.
}

void anotherFunction() {
  // Do Stuff  <-------------- Pointer "p" is out of scope here but still exists!!!!
}

it getting interesting for me...
i think gfvalvo is right.....
one way to test it is printing address of p in good() and then printing values present in the same address.....in c c++ compiler.....but printing values by giving an address,is something not supported by modern operating systems.....may be it can be tested on old operating systems......

The variable "goes out of scope" at the end of the block it was defined in. The function call doesn't change that. The stack frame that contains p is still on the stack, even though you added another frame by calling the function.

It's a matter of linguistics, I think, but that's the way I was taught.

PieterP:
It's a matter of linguistics ....

As I'm sure you know, if you try to reference pointer 'p' from inside 'anotherFunction()' the compiler will complain: "was not declared in this scope". To me, that means 'p' is out of scope at that point.

Indeed.

I think there's confusion between scope and lifetime here. For local variables they are mostly the same, but as you're aware, you can't magically use a variable from within another function, even though its lifetime hasn't ended.