我有以下C++ 11代码:
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;
void f(int a, int b)
{
cout << a << " " << b << endl;
}
void g(int& a, int& b)
{
a *= 2;
b *= 3;
}
int main()
{
int a = 100;
int b = 200;
auto greversed = bind(g,_2,_1);
greversed(b,a);
f(a,b);
greversed(ref(b),ref(a));
f(a,b);
}
Run Code Online (Sandbox Code Playgroud)
基于我对"The C++ Programming Language 4th Edition"(Stroustrup)的解读.968我希望在第一次调用greversed(b,a)期间a和b的副本将通过引用传递给g()并且只有第二个调用实际上会通过引用将a和b传递给g() .
p上给出的示例代码.968:
void incr(int& i)
{
++i;
}
void user()
{
int i =1;
incr(i); // i becomes 2
auto inc = bind(incr,_1);
inc(i); // i stays 2; inc(i) incremented a local copy of i
}
Run Code Online (Sandbox Code Playgroud)
运行此代码,我会增加两次,尽管评论说.
对于我的程序,我的预期输出将是:
100 200
200 600
Run Code Online (Sandbox Code Playgroud)
但是,当我使用"g ++ -std = c ++ 11 test.cpp"在Ubuntu下编译此代码时,我得到以下输出:
200 600
400 1800
Run Code Online (Sandbox Code Playgroud)
无论是否使用ref()适配器,它都会通过引用传递a和b.
Fil*_*efp 19
std::placeholders::_*通过完美转发后来取代它们的类型.
这意味着,因为你正在传递一个和b(这是左值),以greversed这些左值将被转发到g,酷似他们.
此行为[func.bind.bind]p10在标准部分(n3337)中进行了解释,但可以在此处找到更易于理解的解释:
我没有阅读你所指的那本书,但是你的困惑可能在于std::bind当你使用非占位符时不会绑定对传入参数的引用,而是复制参数.
下面的例子有助于理解使用std :: placeholder和传入要绑定的值之间的区别.
int main () {
auto f = [](int& r1, int& r2) {
r1 *= 2;
r2 *= 2;
};
int a = 1;
int b = 2;
auto x = std::bind (f, a, std::placeholders::_1); // a copy of `a` will be stored
// inside `x`
x (b); // pass the copy of `a`, and perfectly-forward `b`, to `f`
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
a: 1
b: 4
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1595 次 |
| 最近记录: |