c++ - std::reference_wrapper 和简单指针有什么区别?

标签 c++ pointers c++11 reference reference-wrapper

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

最佳答案

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

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

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

这行得通,因为……

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

    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() 的函数调用)应该只是内联,因为它们是单行的。

reference_wrapper 是通过 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 限定; r2 引用 const int 并且只会产生对 const int 的引用。调用包含 const 仿函数的引用包装器只会调用 const 成员函数 operator()s。

不允许使用右值初始化器,因为允许它们弊大于利。由于无论如何都会移动右值(并且使用 guaranteed copy elision,即使部分避免了),我们不改进语义;不过我们可以引入悬空指针,因为引用包装器不会延长指针的生命周期。

图书馆互动

如前所述,可以指示 make_tuple 将引用存储在生成的 tuple 中,方法是通过 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 略有不同:此处不允许将右值作为参数。

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

与普通指针的区别

  • 没有额外的语法间接层。必须取消引用指针才能获得指向它们所引用对象的左值; reference_wrapper 有一个隐含的 conversion operator并且可以像它们包装的对象一样被调用。

    int i;
    int& ref = std::ref(i); // Okay
    
  • reference_wrapper 与指针不同,没有空状态。它们必须用 either a reference or another reference_wrapper 初始化.

    std::reference_wrapper<int> r; // Invalid
    
  • 相似之处是浅拷贝语义:指针和 reference_wrapper 可以重新分配。

关于c++ - std::reference_wrapper 和简单指针有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26766939/

相关文章:

c++ - 默认情况下是否应该有任何功能能够就地工作

C++11 可变类处理程序管理器

c++ - 阻止 X3 符号匹配子字符串

c++ - 使用 emplace_back 避免移动构造函数调用的最佳方法?

c++ - 有没有一种优雅的方法可以将 vector<complex<float>> 转换为 vector<short>?

c - 结构体、指针、通过指针获取字段值

c - 我如何更改函数中的指针?

c - 指向接收不需要的垃圾值的单独函数中的数组的指针

c++ - std::error_code 和 std::error_condition 从相同的值和相同的类别构造总是等价的吗?

c++ - boost::asio::io_service async_write 在执行 async_read 时循环