C++ 在callsite参数处创建的临时对象的生命范围

C++ 在callsite参数处创建的临时对象的生命范围,c++,C++,我有下面的代码,我想知道什么时候调用Foo的析构函数 #include <iostream> class Foo { public: Foo() { } ~Foo() { std::cout << "destruct" << std::endl; } }; void go(Foo f) { std::cout << "go" << std::endl; } int main() { go(Foo()

我有下面的代码,我想知道什么时候调用Foo的析构函数

#include <iostream>

class Foo {
public:
  Foo() {
  }
  ~Foo() {
    std::cout << "destruct" << std::endl;
  }
};

void go(Foo f) {
  std::cout << "go" << std::endl;
}

int main() {
  go(Foo());
  std::cout << "main" << std::endl;
  return 0;
}
它显示在go完成后调用Foo的析构函数。我的gcc是4.8.3


我原以为临时Foo的对象在复制到go的参数后应该被删除。但事实并非如此,Foo只存在一个对象。在编译器的实现中,这是预期的还是未定义的?

它是C++标准允许的优化。

< C++标准草案,我和我引用(相关部分,重点是我的):

临时对象的物化通常会延迟 尽可能避免创建不必要的临时对象。

例如:

class X {
public:
  X(int);
  X(const X&);
  X& operator=(const X&);
  ~X();
};

class Y {
public:
  Y(int);
  Y(Y&&);
  ~Y();
};

X f(X);
Y g(Y);

void h() {
  X a(1);
  X b = f(X(2));
  Y c = g(Y(3));
  a = f(a);
}
X(2)
构造在用于容纳
f()
的参数和
Y(3)
构造在用于容纳
g()
的参数的空间中

以前,在年,它说:

一个实现可能会使用一个临时变量来构造
X(2)
在使用
X
的复制构造函数将其传递给
f()
之前; 或者,
X(2)
可以构建在用于容纳 论据

这意味着:

void go(Foo) {
    std::cout << "go" << std::endl;
}

int main() {
    go(Foo());
}
总之,

  • 在本例中,如果不使用
    std::move
    ,则会创建一次对象,如图所示

  • 但是当您使用
    std::move
    时,它会被创建两次,这是因为对象的物化。阅读的完整段落,了解物化的含义


  • go
    使用
    Foo
    ,为什么要在
    go
    使用它之前将其删除?一个真正愚蠢的编译器可以创建一个临时文件,然后将其复制到参数中并删除临时文件,但是如果您所做的只是立即删除它,那么创建临时文件的意义何在?
    void go(Foo) {
        std::cout << "go" << std::endl;
    }
    
    int main() {
        go(Foo());
    }
    
    void go(Foo) {
        std::cout << "go" << std::endl;
    }
    
    int main() {
        go(std::move(Foo()));
    }