Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare stack variable without specifying the name and get the pointer

Tags:

c++

It's known that defining a heap variable with new gets the pointer without specifying the name:

Var *p = new Var("name", 1);

But I have to clear the variable pointed to by p with delete p later on in the program.

I want to declare a stack variable so it is automatically cleared after function exits, but I only want to get the pointer, and the following:

Var v("name", 1);
Var *p = &v;

is quite tedious, and specifier v will never be referenced.

Can I declare a stack class instance and get its pointer without specifying its name?

like image 304
CDT Avatar asked Jun 05 '13 01:06

CDT


3 Answers

There's two questions hidden in here. The first one is:

Var *p = new Var("name", 1);

But I have to clear the variable pointed to by p with delete p later on in the program.

I want to declare a stack variable so it is automatically cleared after function exits

So here, you're asking how to allocate memory without having to explicitly clean it up afterwards. The solution is to use std::unique_ptr:

std::unique_ptr<Var> p(new Var("name", 1));

Voila! unique_ptr will automatically clean itself up, it has virtually no overhead compared to a raw pointer, and it's overloaded the * and -> operators so you can use it just like a raw pointer. Search for "C++11 smart pointers" if you want to know more.

The second question is:

I only want to get the pointer, and the following:

Var v("name", 1);
Var *p = &v;

is quite tedious, and specifier v will never be referenced.

The important point here is that Var *p = &v is completely unnecessary. If you have a function that requires a pointer, you can use &v on the spot:

void SomeFunc(const Var* p);
// ...
Var v("name", 1);
SomeFunc(&v);

There's no need to put &v in a separate variable before passing it into a function that requires a pointer.

The exception is if the function takes a reference to a pointer (or a pointer to a pointer):

void SomeFunc2(Var*& p);
void SomeFunc3(Var** p);

These types of functions are rare in modern C++, and when you see them, you should read the documentation for that function very carefully. More often than not, those functions will allocate memory, and you'll have to free it explicitly with some other function.

like image 161
Rick Yorgason Avatar answered Oct 16 '22 21:10

Rick Yorgason


There's no way to do this by allocating on the stack. However, you can use std::make_shared for the heap:

#include <memory>

std::shared_ptr<Var> p = std::make_shared<Var>();
like image 2
David G Avatar answered Oct 16 '22 22:10

David G


At the cost/risk of being more confusing, you can avoid repeating the type in your code in the question ala:

Var v("name", 1), *p = &v;

You could also potentially use alloca, which is provided by most systems and returns a pointer to stack-allocated memory, but then you have to go through a separate painful step to placement new an object into that memory and do your own object destruction. alloca needs to be called inside the function so it's the function stack on which the object is created, and not during the preparation of function arguments (as the variable's memory may be embedded in the stack area the compiler's using to prepare function arguments), which makes it tricky to wrap into some easily reused facility. You could use macros, but they're evil (see Marshall Cline's C++ FAQ for an explanation of that). Overall - not worth the pain....

Anyway, I recommend sticking with the code in your question and not over-thinking this: using &v a few times tends to be easier, and when it's not it's normally not a big deal if there's an unnecessary identifier for the stack-based variable.

like image 1
Tony Delroy Avatar answered Oct 16 '22 22:10

Tony Delroy