std::reference_wrapper 和简单指针的区别? [英] Difference between std::reference_wrapper and simple pointer?

查看:25
本文介绍了std::reference_wrapper 和简单指针的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么需要 std::reference_wrapper?应该在哪里使用?它与简单的指针有何不同?与简单的指针相比,它的性能如何?

Why is there a need to have std::reference_wrapper? Where should it be used? How is it different from a simple pointer? How its performance compares to a simple pointer?

推荐答案

std::reference_wrapper 与模板结合使用非常有用.它通过存储指向对象的指针来包装对象,允许重新分配和复制,同时模仿其通常的语义.它还指示某些库模板存储引用而不是对象.

std::reference_wrapper is useful in combination with templates. It wraps an object by storing a pointer to it, allowing for reassignment and copy while mimicking its usual semantics. It also instructs certain library templates to store references instead of objects.

考虑 STL 中复制函子的算法:您可以通过简单地传递引用函子而不是函子本身的引用包装器来避免这种复制:

Consider the algorithms in the STL which copy functors: You can avoid that copy by simply passing a reference wrapper referring to the functor instead of the functor itself:

unsigned arr[10];
std::mt19937 myEngine;
std::generate_n( arr, 10, std::ref(myEngine) ); // Modifies myEngine's state

这是有效的,因为......

This works because…

  • reference_wrappers 重载operator() 所以它们可以像它们引用的函数对象一样被调用:

  • reference_wrappers overload operator() so they can be called just like the function objects they refer to:

std::ref(myEngine)() // Valid expression, modifies myEngines state

  • ...(un) 像普通引用一样,复制(和赋值)reference_wrappers 只是赋值指针.

    int i, j;
    auto r = std::ref(i); // r refers to i
    r = std::ref(j); // Okay; r refers to j
    r = std::cref(j); // Error: Cannot bind reference_wrapper<int> to <const int>
    

  • 复制一个引用包装器实际上等同于复制一个指针,它尽可能便宜.使用它固有的所有函数调用(例如对 operator() 的调用)应该只是内联,因为它们是单行的.

    Copying a reference wrapper is practically equivalent to copying a pointer, which is as cheap as it gets. All the function calls inherent in using it (e.g. the ones to operator()) should be just inlined as they are one-liners.

    reference_wrappers 是通过 std::ref 创建的code> 和 std::cref:

    reference_wrappers are created via std::ref and std::cref:

    int i;
    auto r = std::ref(i); // r is of type std::reference_wrapper<int>
    auto r2 = std::cref(i); // r is of type std::reference_wrapper<const int>
    

    模板参数指定所引用对象的类型和cv-qualification;r2 引用一个 const int 并且只会产生对 const int 的引用.调用包含 const 函子的引用包装器只会调用 const 成员函数 operator()s.

    The template argument specifies the type and cv-qualification of the object referred to; r2 refers to a const int and will only yield a reference to const int. Calls to reference wrappers with const functors in them will only call const member function operator()s.

    右值初始值设定项是不允许的,因为允许它们弊大于利.由于无论如何都会移动右值(并且使用 保证复制省略即使部分避免了这种情况),我们也不会改进语义;不过,我们可以引入悬空指针,因为引用包装器不会延长指针的生命周期.

    Rvalue initializers are disallowed, as permitting them would do more harm than good. Since rvalues would be moved anyway (and with guaranteed copy elision even that's avoided partly), we don't improve the semantics; we can introduce dangling pointers though, as a reference wrapper does not extend the pointee's lifetime.

    如前所述,可以通过将相应的参数传递给 reference_wrapper 来指示 make_tuple 在结果 tuple 中存储一个引用:

    As mentioned before, one can instruct make_tuple to store a reference in the resulting tuple by passing the corresponding argument through a reference_wrapper:

    int i;
    auto t1 = std::make_tuple(i); // Copies i. Type of t1 is tuple<int>
    auto t2 = std::make_tuple(std::ref(i)); // Saves a reference to i.
                                            // Type of t2 is tuple<int&>
    

    请注意,这与 forward_as_tuple 略有不同:这里不允许将右值作为参数.

    Note that this slightly differs from forward_as_tuple: Here, rvalues as arguments are not allowed.

    std::bind 显示相同的行为:它如果它是一个 reference_wrapper,则不会复制参数但存储一个引用.如果该参数(或函子!)不需要复制但在使用 bind-函子时保持在范围内,则很有用.

    std::bind shows the same behavior: It won't copy the argument but store a reference if it is a reference_wrapper. Useful if that argument (or the functor!) need not be copied but stays in scope while the bind-functor is used.

    • 没有额外的语法间接层.指针必须被取消引用以获得指向它们所引用对象的左值;reference_wrappers 有一个隐式的转换运算符并且可以被调用就像它们包裹的物体一样.

    • There is no additional level of syntactical indirection. Pointers have to be dereferenced to obtain an lvalue to the object they refer to; reference_wrappers have an implicit conversion operator and can be called like the object they wrap.

    int i;
    int& ref = std::ref(i); // Okay
    

  • reference_wrapper 与指针不同,它没有空状态.它们必须使用 引用或另一个 reference_wrapper.

  • reference_wrappers, unlike pointers, don't have a null state. They have to be initialized with either a reference or another reference_wrapper.

    std::reference_wrapper<int> r; // Invalid
    

  • 一个相似之处是浅拷贝语义:指针和 reference_wrapper 可以重新分配.

    这篇关于std::reference_wrapper 和简单指针的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆