我看过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 中,时间 double
从 int
创建(2) 然后是 bar<const double &>
从中创建并复制到 foo
,而在#2 中,时间 bar<int>
已创建并且是临时的 double
由 bar<int>
的成员创建在 bar<const double&>
的负责人中.似乎时间 double
在 foo
中被破坏在#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/