微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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.

原文地址:https://www.jb51.cc/c/119603.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐