声明堆栈变量而不指定名称并获取指针

时间:2013-06-05 01:43:10

标签: c++

众所周知,使用new定义堆变量会获取指针而不指定名称:

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

但是我必须在程序中稍后用p清除delete p指向的变量。

我想声明一个堆栈变量,因此它会在函数退出后自动清除,但我只想获取指针,以及以下内容:

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

非常乏味,并且永远不会引用说明符v

我是否可以声明堆栈类实例并获取其指针而不指定其名称?

5 个答案:

答案 0 :(得分:10)

这里隐藏着两个问题。第一个是:

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

但是我必须稍后用删除p清除p指向的变量   在节目中。

     

我想声明一个堆栈变量,以便自动清除它   功能退出后

所以在这里,你问的是如何分配内存而不必事后明确地清理它。解决方案是使用std::unique_ptr

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

瞧! unique_ptr会自动清理自己,与原始指针相比几乎没有开销,并且它超载了*和 - &gt;运算符,所以你可以像原始指针一样使用它。如果您想了解更多信息,请搜索“C ++ 11智能指针”。

第二个问题是:

  

我只想获得指针,以及以下内容:

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

非常繁琐,并且永远不会引用说明符v。

这里重点是Var *p = &v完全没必要。如果你有一个需要指针的函数,你可以在现场使用&v

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

在将其传递到需要指针的函数之前,不需要将&amp; v放在单独的变量中。

例外情况是该函数将引用引用到指针(或指向指针的指针):

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

这些类型的函数在现代C ++中很少见,当您看到它们时,您应该非常仔细地阅读该函数的文档。通常情况下,这些函数将分配内存,您必须使用其他函数明确释放它。

答案 1 :(得分:2)

通过在堆栈上分配无法做到这一点。但是,您可以使用std::make_shared作为堆:

#include <memory>

std::shared_ptr<Var> p = std::make_shared<Var>();

答案 2 :(得分:1)

以更加混乱的代价/风险,您可以避免在问题ala中重复代码中的类型

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

您还可以使用alloca,它由大多数系统提供并返回指向堆栈分配内存的指针,但是您必须经历一个单独的痛苦步骤才能放置new一个对象进入那个记忆并做你自己的对象破坏。需要在函数内部调用alloca,因此它是创建对象的函数堆栈,而不是在函数参数的准备期间(因为变量的内存可能嵌入到编译器用于准备函数的堆栈区域中)参数),这使得包装到一些易于重用的设施变得棘手。你可以使用宏,但它们是邪恶的(参见Marshall Cline的C ++ FAQ来解释它)。总的来说 - 不值得痛苦......

无论如何,我建议坚持你的问题中的代码,而不是过度思考:使用&v几次往往更容易,如果不是,通常没有什么大不了的,如果有一个不必要的标识符对于基于堆栈的变量。

答案 3 :(得分:0)

我认为没有办法克服它而没有一些开销(比如shared_ptr)。所以编写它的最短方式是:

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

答案 4 :(得分:-2)

是的,可以将地址返回到临时(即堆栈)对象并将其分配给指针。但是,编译器实际上可能会在当前作用域结束之前丢弃该对象(即导致内存中的该部分被覆盖)。 (澄清:这意味着不要这样做。永远。)请参阅下面评论中关于在不同操作系统上不同版本的GCC中观察到的行为的讨论。 (我不知道版本4.5.3是否仅提供警告而不是错误的事实表明,如果编译时指针在当前范围内的任何地方都有效,那么这将永远是“安全的”使用特定版本的GCC,但我不会指望它。)

这是我使用的代码(根据Jonathan Leffler的建议修改):

#include <stdio.h>

class Class {
public:
    int a;
    int b;
    Class(int va, int vb){a = va; b = vb;}
};

int main(){ 
    Class *p = &Class(1, 2);
    Class *q = &Class(3, 4);
    printf("%p: %d,%d\n", (void *)p, p->a, p->b);
    printf("%p: %d,%d\n", (void *)q, q->a, q->b);
}

使用GCC 4.5.3编译并运行(在Windows 7 SP1上)时,打印此代码:

0x28ac28: 1,2
0x28ac30: 3,4

使用GCC 4.7.1编译并运行时(在Mac OS X 10.8.3上),它打印:

0x7fff51cd04c0: 0,0
0x7fff51cd04d0: 1372390648,32767

在任何情况下,我都不确定为什么你不会正常声明变量并在需要“指针式”的东西的任何地方使用&v(例如,在需要指针作为一个函数的函数中)参数)。