【问题标题】:C++ taking address of temporary when pushing back a pointer to a vector of pointersC++ 在将指针推回指针向量时获取临时地址
【发布时间】:2011-11-25 13:54:46
【问题描述】:

我的代码中出现警告:

警告:获取临时地址

我见过类似的问题,但他们没有回答我的具体问题。

这是我的代码正在做的事情:

vector<A*>* ex_A;

ex_A->push_back( &A());  //I get this warning taking address of temporary

这是未定义的行为吗?

我之前确实有这个,这很好,但我不想担心从堆中删除内存。

vector<A*>* ex_A;

ex_A->push_back( new A());

有人可以向我解释一下警告的含义吗?

【问题讨论】:

  • 你用的是什么编译器? C++ 标准不允许将&amp; 应用于右值。
  • @FredOverflow 是 g++ 4.3。右值代表什么

标签: c++


【解决方案1】:

&amp;A() 正在创建一个临时对象,该对象在完整表达式退出时自动销毁,而new A() 在堆上创建一个新对象,该对象将一直存在,直到您使用 delete 手动销毁它。

我要补充一点,如果你在vector&lt;A*&gt; 中存储使用 new 分配的对象并且向量被破坏,则存储在其中的对象将不会自动删除,因此你会出现内存泄漏。您可以通过在您的程序上使用valgrind --leak-check=full my_compiled_program 来验证这一点,这通常是个好主意。

【讨论】:

  • 谢谢!那么当它超出范围时,指针向量将指向一个悬空指针?
  • 这个答案有几个问题:A() 没有被删除,它被破坏了。这不会发生在块退出时,而是在完整表达式的末尾。当然,编译器发出警告是不对的。它应该是一个完整的错误(根据标准)。
【解决方案2】:

是的,这是未定义的行为。这段代码:

ex_A->push_back( &A());

将构造一个A的临时实例,然后将其地址添加到一个vector中,然后销毁该实例并回收A占用的存储空间以供重复使用。向量内的指针将变得悬空 - 无法保证将在该地址进一步分配什么,并且使用该地址是未定义的行为。

【讨论】:

  • 嗯,这不是未定义的行为。例如,您可以使用集合中的指针来播种随机数生成器...取消引用任何指针都是不好的。
  • @Kerrek SB:不,即使读取那些指针值已经是 UB。
  • 哦,有趣。那是哪里来的?我想这允许编译器完全省略临时对象的创建。
  • @KerrekSB 这条规则的动机是在一些古老的处理器中使用单独的地址和整数寄存器。其中一些会在加载时验证地址。在这种特殊情况下,我不认为内存真的有可能失效,但在其他情况下,这种可能性是存在的,标准的作者希望支持这些。今天,它仍然是未定义的行为,但我不会太担心。
【解决方案3】:

A() 是一个临时变量,在语句结束时将不复存在。当你获取它的地址时,你会得到一个很快就会失效的指针,下次你尝试取消引用该指针时,你会得到未定义的行为。

【讨论】:

    【解决方案4】:

    考虑您创建的数据的范围。在第一种情况下,您在堆栈上创建一个对象,存储它的地址,然后,当它超出范围时,存储的指针指向的数据被删除。

    在第二种情况下,您在堆上分配,在您退出块并且存储的指针指向有效数据后,数据仍然“活动”。

    【讨论】:

      【解决方案5】:

      ex_A->push_back(&A());

      在这一行中,通过使用 & 您正在获取堆栈上指针的地址,一旦您离开您的函数范围,该地址将不再有效,因此您必须使用 (new A())分配内存。

      【讨论】:

        【解决方案6】:

        只要你在 C++ 中工作,你就必须照顾内存......如果你想避免这种转变!
        我认为你需要对谁将拥有你的向量中的项目做出决定——如果它是向量,那么

        ex_A->push_back(new A());
        

        很好 - 但您只需要在删除/完成删除该对象时照顾它。
        你不能

        ex_A->push_back(&A());  
        

        因为 A() 在堆上并且会超出范围并在当前范围结束时被删除。你想要的是让一个对象保持活动状态,而不必担心谁会删除它 -> 你需要 C# 或 Java。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-14
          • 1970-01-01
          • 2013-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-30
          相关资源
          最近更新 更多