隐式铸造临时对象的生命周期
我看过这个问题。 看来,无论进行何种强制转换,临时对象都会“生存”,直到评估完整表达式为止。 但在以下场景中:
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
并且只有 2 个失败。
@update
我在原帖中使用 struct bar 而不是 boost::tuple
,希望其他人会更熟悉。
让我把我的问题说得更清楚。在 #1 中,从 int
(2) 创建一个时间 double
,然后从中创建一个 bar
并复制到 foo
中,而在 #2 中,创建了一个临时 bar
并从 < 的成员创建了一个临时 double
bar
的构造函数中的 code>bardouble
在 #2 中的 foo
中被破坏,而在 #1 中则没有。为什么?我认为它们都是完整表达式的一部分,并且应该存在直到 bar
返回。
Tim 说“编译器足够聪明,可以将这个 2 视为 double 而不是 int。”。所以我写了 int i = 2;
并将 i
传递给这两个调用,但事情还是像以前一样进行。我是在VS2008下用调试模式做的。
I have seen this question.
It seems that regardless of the cast, the temporary object(s) will "survive" until the fullexpression evaluated.
But in the following scenario:
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 run well, but 2 do not.
And MSVC gave me a warning about 2: "reference member is initialized to a temporary that doesn't persist after the constructor exits"
Now I am wondering why they both make a temporary double
object and pass it to bar<const double&>
and only 2 failed.
@update
I use struct bar instead of boost::tuple
in the original post, hope it will be more familiar to others.
Let me make my question more clear. In #1, a temporal double
is created from int
(2) and then a bar<const double &>
is created from it and copied into foo
, while in #2, a temporal bar<int>
is created and a temporal double
is created from the member of bar<int>
in the ctor of bar<const double&>
. It seems that the temporal double
is destructed in foo
in #2 while do not in #1. Why? I think they are all part of the fullexpression and shall be exist until bar
return.
Tim says "The compiler is smart enough to treat this 2 as a double instead of an int.". so I wrote int i = 2;
and passed i
to both of the two calls, but things go on like before. I made it in VS2008 with debug mode.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
.#1 调用(2)) 创建一个临时的 double 。然后创建一个临时的
boost::tuple::tuple(const double&)
。为此,由完整表达式 foo(boost::tupleboost::tuple
。它有一个绑定到临时double
的引用成员。两个临时变量都存在,直到完整表达式 #1 完成为止,并且在调用foo
时仍然有效。.#2 调用
boost::tuple::tuple(const boost::tuple&)
。此表达式创建一个临时boost::tuple
。该临时对象的生命周期同样不是问题。但请考虑调用该元组构造函数时会发生什么。简化/伪代码类:mem-initializer
member1(int_tup.member1_)
将int
值转换为临时double
并绑定该double
到类引用成员。这个临时double
是由完整表达式member1_(int_tup.member1_)
创建的,而不是由完整表达式foo(boost::make_tuple(2)) 创建的
。 mem-initializers 的一个特殊例外保证临时double
在创建它的构造函数结束之前都是可以的,但是不能保证它在foo
时仍然有效被称为。因此,重要的区别在于语句 #1 本身创建临时
double
,但语句 #2 间接导致在另一个函数内创建临时double
。确切地哪个完整表达式创建一个临时对象会影响该临时对象的生存时间。.#1 calls
boost::tuple<const double&>::tuple(const double&)
. In order to do this, a temporarydouble
is created by the full-expressionfoo(boost::tuple<const double&>(2))
. Then a temporaryboost::tuple<const double&>
is created. It has a reference member which is bound to the temporarydouble
. Both temporaries exist until full-expression #1 is done, and is still valid whenfoo
is called..#2 calls
boost::tuple<const double&>::tuple(const boost::tuple<int>&)
. This expression creates a temporaryboost::tuple<int>
. The lifetime of that temporary is similarly not a problem. But consider what happens when thattuple
constructor is called. Simplified / pseudocode classes:The mem-initializer
member1(int_tup.member1_)
converts theint
value to a temporarydouble
and binds thatdouble
to the class reference member. This temporarydouble
is created by the full-expressionmember1_(int_tup.member1_)
, not by the full-expressionfoo(boost::make_tuple(2))
. A special exception for mem-initializers guarantees that the temporarydouble
is okay until the end of the constructor in which it was created, but then there's no guarantee it's still valid whenfoo
is called.So the important difference is that statement #1 creates the temporary
double
itself, but statement #2 indirectly causes a temporarydouble
to be created within another function. Exactly which full-expression creates a temporary has an impact on how long that temporary will live.在 #2 中,时间的构造函数完成时,D 就会被破坏。
tuple
由tuple
构造而成作为
foo
的参数n
。在构建
tuple
之前,时间 double(D) 是由
tuple
的 int 成员和double const&
构造而成成员初始化为 D。
为准备函数参数而构造的时态对象被破坏
当函数调用完成时。
因此,当 tuple
希望这有帮助
In #2, a temporal
tuple<double const&>
is constructed fromtuple<int>
as the argument
n
forfoo
.Before
tuple<double const&>
's construction, a temporal double(D) isconstructed from an int member of
tuple<int>
, and thedouble const&
member is initialized as D.
Temporal objects constructed to prepare function arguments are destructed
when the function call is completed.
So, D is destructed when
tuple<double const&>
's constructor finishes.Hope this helps
我相信第 1 行是可以的,因为允许 const 引用来引用临时对象。有人可能可以引用这方面的标准。
I believe line #1 is OK because const references are allowed to refer to temporaries. Somebody can probably quote the standard on that.
前言:我不是 Boost 或 Tuple 专家。我也从来没有用过。无论如何,我会尽力提供帮助。
在我看来,
boost::make_tuple(2)
正在返回一个tuple
。但是,似乎进行了隐式转换以匹配您的foo
实现,在此期间它可能会尝试获取临时地址(将int
转换为>const double&
) 不恰当。您是否尝试过显式转换您的
make_tuple
?再说一遍,我不是增强或元组专家,但我会尝试:
或者
我承认我在这里进行了有根据的猜测,试图提供帮助,所以我不保证这是正确的树。
Preface: I am not a Boost or Tuple expert. I've never used either. I will attempt to be helpful anyway.
It appears to me that
boost::make_tuple(2)
is returning atuple<int>
. However, there appears to be an implicit cast done to match yourfoo
implementation, during which time it may be attempting to take the address of the temporary (convertingint
toconst double&
) inappropriately.Have you tried explicitly casting your
make_tuple
?Again, I'm not a boost or tuple expert, but I would try:
or
I admit I'm taking an educated guess here in an attempt to help, so I don't promise this is the right tree to bark up.