返回语句复制值

ldo*_*dog 65 c++ return

由于范围问题,我对此感到疑惑.例如,考虑代码

typedef struct {
    int x1;/*top*/
    int x2;/*bottom*/
    int id;
} subline_t;



subline_t subline(int x1, int x2, int id) {
    subline_t t = { x1, x2, id };
    return t;
}

int main(){
    subline_t line = subline(0,0,0); //is line garbage or isn't it? the reference
    //to subline_t t goes out of scope, so the only way this wouldn't be garbage
    //is if return copies
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,返回语句是否总是复制?在这种情况下,它似乎工作,所以我被引导相信返回确实复制.如果它复制了,它会在每种情况下复制吗?

Gre*_*ill 43

是的,在这种情况下会有一份副本.如果你改变这样的函数声明:

subline_t &subline(int x1, int x2, int id) {
Run Code Online (Sandbox Code Playgroud)

然后不会复制.但是,在您的特定情况下,返回对堆栈上分配的对象的引用是无效的.问题是在调用者有机会使用它之前,对象将被破坏并失效.

这与C++ 的常见返回值优化有关,可以避免在您描述的情况下执行实际的复制操作.最终结果是(或应该)与复制完成时相同,但您应该了解优化.在某些情况下,这种优化的存在可以改变程序的可观察行为.

  • 您不应该返回对临时对象的引用. (17认同)
  • 如果您已经进一步阅读,您还会看到链接文章后来说:"术语返回值优化是指C++标准中的一个特殊子句,它允许实现省略由return语句产生的复制操作,甚至如果复制构造函数有副作用,那么as-if规则本身就不允许这样做." (8认同)
  • @ Steve314:使用`&`,在问题中描述的情况下不会进行复制,但结果程序操作将是未定义的.但是,如果返回的对象不是本地范围的变量,那将是完全合法的. (3认同)

Tom*_*Tom 5

在你的情况下,它将返回一份副本

如果你的代码是

subline_t& subline(int, int)
Run Code Online (Sandbox Code Playgroud)

那么它会返回一个引用,这会产生未定义的行为。

  • 返回引用本身并不是未定义的行为。返回对本地对象的引用是,但返回对全局、静态、“this”字段或堆分配对象的引用是完全可以的。 (4认同)