我有以下代码:
#include <stdio.h>
#include <functional>
template <typename T>
auto callback(T&& func) ->decltype(func())
{
return func();
}
double test(double& value)
{
value=value+1.0;
return value;
}
int main(void)
{
double t=1.0;
printf("%f\n",t);
test(t);
printf("%f\n",t);
callback(std::bind(test,t));
printf("%f\n",t);
}
Run Code Online (Sandbox Code Playgroud)
它输出
1.000000
2.000000
2.000000
Run Code Online (Sandbox Code Playgroud)
这意味着该callback
函数获得了副本t
而不是引用t
.我想知道发生了什么,因为std::bind
它应该是完美的转发.
R. *_*des 36
std::bind
默认情况下使用值语义.这是一个理智的默认设置,可让您安全地执行以下操作.
int f(double x);
auto fun = std::bind(f, 1.0); // stores a copy, not a reference to a temporary
fun();
Run Code Online (Sandbox Code Playgroud)
使用值语义是安全的:绑定参数的生命周期成为bind返回的对象的生命周期.使用引用语义不具备这种保证.因此,当您需要引用语义时,您需要明确; 如果你遇到麻烦,那就是你的错.为此,您需要使用std::ref
:
int main(void)
{
double t=1.0;
printf("%f\n",t);
test(t);
printf("%f\n",t);
callback(std::bind(test, std::ref(t)));
printf("%f\n",t);
}
Run Code Online (Sandbox Code Playgroud)
这个相同的协议在标准库的其他地方使用,就像std::thread
构造函数一样.
std::bind()
是为价值语义而设计的(正如R. Martinho Fernandes在他的回答中很好地解释的那样),并在内部创建副本.你需要/想要的是std::ref
:
callback(std::bind(test, std::ref(t)));
// ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
std::ref
返回一个std::reference_wrapper<>
包装对原始参数的引用的对象.这样,reference_wrapper
周围的对象t
被复制,而不是t
自身.
这允许您在值语义(默认情况下假定)和引用语义(需要您的显式干预)之间进行选择.
这是一个实例.
归档时间: |
|
查看次数: |
6276 次 |
最近记录: |