【问题标题】:Is it possible to change the temporary object and to pass it as an argument?是否可以更改临时对象并将其作为参数传递?
【发布时间】:2010-12-07 00:03:56
【问题描述】:

是否可以更改临时对象并将其作为参数传递?

struct Foo {    
   Foo& ref() { return *this; }
   Foo& operator--() { /*do something*/; return *this; }
   // another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}

int main() {
   func_val(--getfoo());     // #1 OK?
   func_ref(getfoo());       // #2 OK?
   func_ref(getfoo().ref()); // #3 OK?
   // the following line is a real example 
   //    using --vector.end() instead of --getfoo()
   func_ref(--getfoo());     // #4 OK? 

   const Foo & xref = --getfoo(); //  Does const extend the lifetime ?
   func_ref(xref);     // #5 OK? 
   func_val(xref);     // #6 OK? 

}

众所周知,将临时对象分配给 const 引用会延长该临时对象的生命周期。那么我的代码的#4 和#5 行呢? 引用 x 在函数 func_ref 中是否始终有效是真的吗? 问题是 operator-- 返回了一些引用,编译器看不到这个引用和我们创建的临时值之间的任何关系。

【问题讨论】:

  • 您能否详细说明代码的目标?作为一个抽象问题很有趣,但有时最好的答案可能不在您选择的路线上。
  • 请详细信息std::for_each(vector.begin(), --vector.end(), Functor());const Iter & endminus = --vector.end(); std::for_each(vector.begin(), endminus, Functor());

标签: c++ reference temporary const-reference


【解决方案1】:

临时对象总是存在于创建它们的完整表达式的生命周期中。因此,在 表达式语句 func_val(--getfoo()); 中,getfoo() 表达式返回的临时变量的生命周期不需要任何扩展。声明直到func_val() 返回后才结束。

【讨论】:

  • 这是我一直有的一个问题,并且没有设法以这种方式解释标准。我真的不确定临时的生命周期是否会一直延伸到函数调用的完成。您对定义它的标准有任何指示吗?
  • 这不是陈述,而是完整的表达。这是显着的不同。虽然在表达式语句中,该语句与完整表达式等效,但在其他上下文中,则不是,如 if(func_ref(getfoo())) { /* now, the object returned by getfoo() is already destroyed, even though we are still in the same if-statement */ }
【解决方案2】:
func_val(--getfoo());     // #1 OK?

是的,好的。 operator-- 是一个成员函数,它被调用并返回自身(左值引用自身)。然后将该对象复制到func_val 的参数中。请注意,不允许应用返回值优化,因为 getfoo() 创建的临时值之前已绑定到引用。

func_ref(getfoo());       // #2 OK?

是的,好的。调用 getfoo() 返回一个绑定到 const 引用的临时值。需要一个复制构造函数,但调用它可能会被实现优化。临时持续到包含对func_ref 的调用的完整表达式结束(此处为整个表达式语句)。

func_ref(getfoo().ref());

是的,好的。不需要复制构造函数,因为我们将 const 引用绑定到不是临时的,而是绑定到表示对象本身的左值。

// the following line is a real example 
//    using --vector.end() instead of --getfoo()

这不是工作所必需的。想想vector.end() 返回T*(允许)的情况。你不能修改非类类型的右值,所以在这种情况下,这将是不正确的。

func_ref(--getfoo()); 

是的,好的。参数的计算方式与#1 中一样,但结果左值直接传递,并且 const 引用绑定到它。从这个意义上说,它等于#3(减量副作用除外)。

const Foo & xref = --getfoo();

标准的措辞并不完全清楚。它肯定只打算延长尚未绑定到引用的对象的生命周期。但在我们的例子中,--getfoo() 产生一个左值,它指向一个之前绑定到引用的临时对象。向委员会提交一份缺陷报告可能是值得的(我也可能遗漏了要求临时对象不受参考约束的措辞)。

在任何情况下,预期的行为都是在初始化xref 结束时破坏由getfoo() 产生的临时,因此xref 将成为一个悬空引用。

问题是操作符--返回一些引用,编译器看不到这个引用和我们创建的临时值之间的任何关系。

完全正确(但仅适用于xref 的初始化,这会发疯。在所有其他情况下,您想要的预期行为(或我相信您想要的)都已实现)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 2013-03-20
    • 2015-10-07
    相关资源
    最近更新 更多