c++ - 隐式类型转换的临时工的生命周期

标签 c++ casting temporary lifetime

我看过this question . 似乎无论转换如何,临时对象都将“存活”到 fullexpression 被评估为止。 但是在下面的场景中:

template<class T>
struct bar {
    T t;
    bar(T t) : t(t) {}
    template<class U>
    bar(bar<U> other) : t(other.t) {}
};
void foo(bar<const double&> b) {
    printf("%lf\n", b.t);
}
int main() {
    foo(bar<const double&>(2));//#1
    foo(bar<int>(2));          //#2
    return 0;
}

1 运行良好,但 2 运行不佳。 MSVC 给了我一个关于 2 的警告:“引用成员被初始化为一个临时的,在构造函数退出后不会持续存在”

现在我想知道为什么他们都制作一个临时的 double对象并将其传递给 bar<const double&>只有 2 个失败了。

@更新

我使用 struct bar 而不是 boost::tuple在原帖中,希望其他人会更熟悉。

让我更清楚地说明我的问题。在 #1 中,时间 doubleint 创建(2) 然后是 bar<const double &>从中创建并复制到 foo ,而在#2 中,时间 bar<int>已创建并且是临时的 doublebar<int> 的成员创建在 bar<const double&> 的负责人中.似乎时间 doublefoo 中被破坏在#2 而不是在#1。为什么?我认为它们都是完整表达式的一部分,将一直存在到bar。返回。

Tim 说“编译器足够聪明,可以将此 2 视为 double 而不是 int。”。所以我写了int i = 2;并通过了i两个电话,但事情像以前一样继续。我是在 VS2008 中用 Debug模式制作的。

最佳答案

.#1 调用 boost::tuple<const double&>::tuple(const double&) .为此,临时 double由完整表达式 foo(boost::tuple<const double&>(2)) 创建.然后临时boost::tuple<const double&>被 build 。它有一个绑定(bind)到临时 double 的引用成员.两个临时对象都存在,直到完整表达式 #1 完成,并且在 foo 时仍然有效。被称为。

.#2 调用 boost::tuple<const double&>::tuple(const boost::tuple<int>&) .此表达式创建一个临时的 boost::tuple<int> .该临时文件的生命周期同样不是问题。但是考虑一下当 tuple 时会发生什么构造函数被调用。简化/伪代码类:

template<> class tuple<int> {
  private:
    int member1_;
  //...
};

template<> class tuple<const double&> {
  private:
    const double& member1_;
  public:
    tuple(const tuple<int>& int_tup) : member1_(int_tup.member1_) {}
  // ...
};

内存初始化器 member1(int_tup.member1_)转换 int临时值 double并绑定(bind) double给类引用成员。这个临时double由完整表达式 member1_(int_tup.member1_) 创建,而不是完整表达式 foo(boost::make_tuple(2)) . mem-initializers 的一个特殊异常(exception)保证临时 double在创建它的构造函数结束之前是可以的,但是不能保证它在 foo 时仍然有效。被称为。

所以重要的区别在于语句#1 创建了临时 double本身,但语句 #2 间接导致临时 double在另一个函数中创建。确切地说,哪个完整表达式创建了一个临时对象,这会影响该临时对象的生存时间。

关于c++ - 隐式类型转换的临时工的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4526961/

相关文章:

c++ - finally函数依赖RVO

c++ - 将 Linux system() 调用命令的输出重定向到一个变量

ruby-on-rails - 使用 STI 时如何将 ActiveRecord 对象转换为另一个类?

c++ - 说明 : Converting 'char **' to 'const char **' , 转换失去限定符

java - 无法将对象转换为可比对象

Fortran 运行时警告 : temporary array

oracle - 我们如何在 pl/sql block 中使用 oracle 私有(private)临时表?

c++ - 免费编译器 + IDE,用于用 C++ 编写 Windows 应用程序(面向学生)

c++ - 动态内存和 "ordinary"内存的区别

shell - 来自 Emacs 的外部进程调用期间的临时修改环境