c – 如何通过引用将函数绑定到对象?

我有以下代码将成员函数绑定到类的实例:
class Foo {
public:
    int i;
    void test() {
        std::cout << i << std::endl;
    }
};

int main() {
    Foo f;
    f.i = 100;
    auto func = std::bind(&Foo::test,std::forward<Foo>(f));
    f.i = 1000;
    func();
}

但是std :: bind语句没有通过引用绑定到f.调用func打印“100”而不是“1000”,这就是我想要的.

但是,如果我更改语句以获取指针它是否有效.

auto func = std::bind(&Foo::test,&f);

但这是通过我的理解通过指针传递f,并且我认为std :: bind采用r值参考Arg&& (如图here所示)这怎么工作?

有人可以解释一下吗?

解决方法

关于使用std :: forward的注意事项

首先,std :: forward意味着用于perfect forwarding,即转发引用类型(l值或r值).

如果将l值引用传递给返回的std :: forward,同样如果传递了r值引用,则返回r值.这与std :: move相反,它将始终返回r值引用.还要记住,命名的r值引用是l值引用.

/* Function that takes r-value reference. */
void func(my_type&& t) {
    // 't' is named and thus is an l-value reference here.

    // Pass 't' as lvalue reference.
    some_other_func(t);
    // Pass 't' as rvalue reference (forwards rvalueness).
    some_other_func(std::forward<my_type>(t));
    // 'std::move' should be used instead as we kNow 't' is always an rvalue.
    // e.g. some_other_func(std::move(t));
}

此外,您永远不应该在您之后需要访问某个状态的对象上使用std :: forward或std :: move.移动的对象被置于未指定但有效的状态,这基本上意味着除了销毁或重新分配状态之外,你不能对它们做任何事情.

通过引用std :: bind传递的参数?

函数std :: bind将始终复制或移动其参数.我找不到标准的适当引用,但en.cppreference.com says

“The arguments to bind are copied or moved,and are never passed by reference unless wrapped in std::ref or std::cref.”

这意味着如果您将参数作为l值引用传递,则它是复制构造的,如果将其作为r值引用传递,则它将被移动构造.无论哪种方式,参数都不会作为参考传递.

为了避免这种情况你可以例如使用std::ref作为可复制的引用包装器,它将在内部保持对调用站点的变量的引用.

auto func = std::bind(&Foo::test,std::ref(f));

或者您可以按照建议简单地将指针传递给f.

auto func = std::bind(&Foo::test,&f);

然后发生的是std :: bind将对从f上调用address-of运算符返回的临时指针的r值引用.此指针将被复制(因为指针无法移动)到std :: bind返回的绑定包装器对象中.即使指针本身被复制,它仍将指向调用站点上的对象,您将获得所需的引用语义.

或者使用lambda通过引用捕获f并调用函数Foo :: test.这是恕我直言的推荐方法,因为在一般情况下,lambdas比std :: bind表达式更通用,更强大.

Foo f;
f.i = 100;
auto func = [&f] { f.test(); };
f.i = 1000;
func(); // 1000

注意:有关何时使用std :: forward的详细说明,请参阅this excellent video by Scott Meyers.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...