【问题标题】:c++ taking the address of a temporary object [duplicate]c ++获取临时对象的地址[重复]
【发布时间】:2015-05-04 14:33:54
【问题描述】:

我有两个预期结果相同的代码段:

第一个:

SomeClass somefunc(...){
    SomeClass newObj;
    //some codes modify this object
    return newObj;
}

int main(){
    SomeClass *p;
    p = &(somefuc(...));
}

第二个:

SomeClass *somefunc(...){
    SomeClass newObj;
    //some codes modify this object
    return &newObj;
}

int main(){
    SomeClass *p;
    p = somefunc(...);
}

为什么在我尝试构建第一个代码段时出现“获取临时对象的地址”错误,而第二个代码段没有产生错误?

【问题讨论】:

  • 请显示您的实际代码。
  • 两个片段都无法编译。第二个是因为您尝试从声明返回SomeClass 的函数中返回SomeClass*。另请注意,newObj 不是临时的 - 它是一个命名变量。获取地址没有问题 - 问题在于在变量的生命周期结束后使用所述地址。
  • 第二个例子甚至不应该编译,p = &(somefuc(...)); 也不应该编译,因为你不能获取右值的地址
  • @BaummitAugen 这个问题肯定存在(在第二个例子中),但与手头的问题无关(在第一个例子中)。不是重复的。
  • 我猜你在第二个例子中是指SomeClass *somefunc(...){

标签: c++


【解决方案1】:

在你考虑这个之前,你需要学习临时生命的规则。

广泛的情况是临时对象在创建它的完整表达式结束时被销毁。这意味着如果

SomeClass *p;
p = &(somefunc(...));

被允许工作,p 将是一个悬空指针,指向一个不再存在的对象。

上述规则的一个大例外是,当具有自动生命周期的引用直接绑定到临时对象时,临时对象的生命周期会延长到等于引用的生命周期。请注意,这不包括 const T& make_lvalue(const T& t) { return t; },因为引用不是直接绑定的,也不是类成员引用。

有一些情况是完全安全的,其中临时地址仅立即使用,不存储以备后用。例如

memcpy(buffer, &f(), sizeof(decltype(f())));

当然,这会导致您遇到“临时地址”错误,但您可以通过

memcpy(buffer, std::addressof(f()), sizeof(decltype(f())));

但不要存储结果指针。

【讨论】:

    【解决方案2】:

    第一个 sn-p 没有编译是正确的,因为正如编译器所说,你不能获取临时对象的地址,因为它会在表达式的末尾被破坏(这里:赋值)。因此,保存它的地址是没有意义的。

    第二个 sn-p 确实编译,但仍然不正确,尽管它似乎可以工作,原因是 here(至少如果您尝试通过指针访问对象)。

    【讨论】:

      【解决方案3】:

      第一个示例无法编译,因为 somefunc 返回一个值,并且您尝试获取它返回的这个临时对象的地址。这会起作用:

      Someclass* p;
      Someclass  val = somefunc (...);
      p = &val;
      

      第二个例子没有编译——或者不应该编译——因为 somefunc 应该返回一个 Someclass,而是返回一个指向 Someclass 的指针。让它返回 Someclass* 然后它应该编译 - 但现在你返回一个指向局部变量的指针,在你离开函数后它不再存在。最佳解决方案是第一个示例,此处已修补。

      【讨论】:

      • 第二个例子......“应该工作”什么?它返回一个悬空指针,绝对没用。你最好返回void
      • 啊,是的。我已经编辑了我的答案来说明这一点。
      猜你喜欢
      • 2011-03-21
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多