optional<reference_wrapper<T>> 与 optional<T>& - 实际例子?
optional<reference_wrapper<T>> vs. optional<T>& - practical examples?
我读过 std::optional<std::reference_wrapper<T>>
作为传递可选引用的方法。
但是,我想不出一个实际的例子,我会这样做,而不是仅仅使用 optional<T>&
。
例如,假设我正在编写一个需要通过引用获取可选 vector<int>
的函数。
我能做到:
void f(optional<reference_wrapper<vector<int>>> v) {
// ...
}
int main() {
vector<int> v = {1, 2, 3, 4};
f(make_optional<reference_wrapper<vector<int>>>(std::ref(v));
return 0;
}
但为什么不这样做呢?
void f(optional<vector<int>>& v) {
// ...
}
int main() {
f(make_optional<vector<int>>>(std::initializer_list{1, 2, 3, 4}));
return 0;
}
请举例说明 optional<reference_wrapper<T>>
优于 optional<T>&
。我不清楚语义差异,尤其是它们在实践中的利用方式。
std::optional<T> &
是对可以拥有 T
对象的可选对象的引用。您可以改变 T
(如果包含一个)或者您可以清除通过引用传入的可选对象,破坏包含的 T
.
std::optional<std::reference_wrapper<T>>
是一个可选对象,它可以拥有对 T
、 的引用,但它实际上并不拥有 T
本身。 T
生活在 std::optional
对象的 之外 。您可以改变 T
(如果包含引用)或者您可以清除可选对象,这 不会 破坏 T
。您还可以使可选对象指向不同的 T
,但这有点毫无意义,因为调用者正在向您传递一个可选的 by 值。
请注意,我们已经 有一个内置于语言的类型,表示 "optional reference to a T
":T*
。原始指针和可选引用具有基本相同的语义:要么什么也得不到,要么得到不属于你的对象的句柄。在现代 C++ 中,原始指针是表达接收者不拥有的可选值的方式。
我想不出我曾经明确使用 std::optional<std::reference_wrapper<T>>
而不是 T*
的单一原因。
But why not just do this?
因为您的代码无法编译。 make_optional
returns 纯右值,并且不能将纯右值传递给采用非 const
左值引用的函数。
这很重要,因为它显示了这两种情况之间的根本区别。如果您已经有一个 T
或来自其他地方的对 T
的引用,那么您 不能 将其传递给接受 optional<T>&
的函数.您必须将 T
复制到 optional<T>
变量中,然后将对 optional
变量的引用传递给函数。
你无法修改外界的T
。这就是不同之处:使用 reference_wrapper<T>
,您可以。
或者,如果您有一个函数可以使用或不使用可修改的 T
,您可以像大多数人一样传递 T*
。
正如其他答案所述,这两种类型有不同的用途,因为引用是指不同的事物(在一种情况下引用 optional
而在另一种情况下引用 vector
其他)。无需重复解释,这里有一些您可以尝试查看功能差异的代码。
#include <iostream>
#include <vector>
#include <functional>
#include <optional>
// For better readability:
using optional_reference_vector = std::optional<std::reference_wrapper<std::vector<int>>>;
using optional_vector = std::optional<std::vector<int>>;
void f(optional_reference_vector v) {
v->get().push_back(5);
}
void g(optional_vector & w) {
w->push_back(5);
}
int main() {
// Two identical vectors with which to work:
std::vector<int> v = {1, 2, 3, 4};
std::vector<int> w = {1, 2, 3, 4};
// Demonstrate an optional reference to a vector
// ---------------------------------------------
// Create a reference to `v` in `opt_v`.
// Changes to `opt_v` will be reflected in `v` (and vice versa).
optional_reference_vector opt_v {std::ref(v)};
v.clear();
// A copy of `opt_v` will be made in f(). Since we are copying a reference to
// a vector and not the vector itself, the vector in main() is changed by f().
f(opt_v);
// Both `v` and `opt_v` refer to the same vector, so the size is the same.
std::cout << "Using a reference to the vector:\n"
<< "Original vector size: " << v.size() << '\n'
<< "Optional vector size: " << opt_v->get().size() << "\n\n";
// Demonstrate a reference to an optional vector
// ---------------------------------------------
// Copy `w` into `opt_w`.
// Changes to `opt_w` have no effect on `w` (and vice versa).
optional_vector opt_w {w};
w.clear();
// A reference to `opt_w` will be used in g(), so `opt_w` is updated.
g(opt_w);
// There are two vectors that now have different sizes.
std::cout << "Using a copy of the vector:\n"
<< "Original vector size: " << w.size() << '\n'
<< "Optional vector size: " << opt_w->size() << '\n';
return 0;
}
这段代码的输出:
Using a reference to the vector:
Original vector size: 1
Optional vector size: 1
Using a copy of the vector:
Original vector size: 0
Optional vector size: 5
我读过 std::optional<std::reference_wrapper<T>>
作为传递可选引用的方法。
但是,我想不出一个实际的例子,我会这样做,而不是仅仅使用 optional<T>&
。
例如,假设我正在编写一个需要通过引用获取可选 vector<int>
的函数。
我能做到:
void f(optional<reference_wrapper<vector<int>>> v) {
// ...
}
int main() {
vector<int> v = {1, 2, 3, 4};
f(make_optional<reference_wrapper<vector<int>>>(std::ref(v));
return 0;
}
但为什么不这样做呢?
void f(optional<vector<int>>& v) {
// ...
}
int main() {
f(make_optional<vector<int>>>(std::initializer_list{1, 2, 3, 4}));
return 0;
}
请举例说明 optional<reference_wrapper<T>>
优于 optional<T>&
。我不清楚语义差异,尤其是它们在实践中的利用方式。
std::optional<T> &
是对可以拥有 T
对象的可选对象的引用。您可以改变 T
(如果包含一个)或者您可以清除通过引用传入的可选对象,破坏包含的 T
.
std::optional<std::reference_wrapper<T>>
是一个可选对象,它可以拥有对 T
、 的引用,但它实际上并不拥有 T
本身。 T
生活在 std::optional
对象的 之外 。您可以改变 T
(如果包含引用)或者您可以清除可选对象,这 不会 破坏 T
。您还可以使可选对象指向不同的 T
,但这有点毫无意义,因为调用者正在向您传递一个可选的 by 值。
请注意,我们已经 有一个内置于语言的类型,表示 "optional reference to a T
":T*
。原始指针和可选引用具有基本相同的语义:要么什么也得不到,要么得到不属于你的对象的句柄。在现代 C++ 中,原始指针是表达接收者不拥有的可选值的方式。
我想不出我曾经明确使用 std::optional<std::reference_wrapper<T>>
而不是 T*
的单一原因。
But why not just do this?
因为您的代码无法编译。 make_optional
returns 纯右值,并且不能将纯右值传递给采用非 const
左值引用的函数。
这很重要,因为它显示了这两种情况之间的根本区别。如果您已经有一个 T
或来自其他地方的对 T
的引用,那么您 不能 将其传递给接受 optional<T>&
的函数.您必须将 T
复制到 optional<T>
变量中,然后将对 optional
变量的引用传递给函数。
你无法修改外界的T
。这就是不同之处:使用 reference_wrapper<T>
,您可以。
或者,如果您有一个函数可以使用或不使用可修改的 T
,您可以像大多数人一样传递 T*
。
正如其他答案所述,这两种类型有不同的用途,因为引用是指不同的事物(在一种情况下引用 optional
而在另一种情况下引用 vector
其他)。无需重复解释,这里有一些您可以尝试查看功能差异的代码。
#include <iostream>
#include <vector>
#include <functional>
#include <optional>
// For better readability:
using optional_reference_vector = std::optional<std::reference_wrapper<std::vector<int>>>;
using optional_vector = std::optional<std::vector<int>>;
void f(optional_reference_vector v) {
v->get().push_back(5);
}
void g(optional_vector & w) {
w->push_back(5);
}
int main() {
// Two identical vectors with which to work:
std::vector<int> v = {1, 2, 3, 4};
std::vector<int> w = {1, 2, 3, 4};
// Demonstrate an optional reference to a vector
// ---------------------------------------------
// Create a reference to `v` in `opt_v`.
// Changes to `opt_v` will be reflected in `v` (and vice versa).
optional_reference_vector opt_v {std::ref(v)};
v.clear();
// A copy of `opt_v` will be made in f(). Since we are copying a reference to
// a vector and not the vector itself, the vector in main() is changed by f().
f(opt_v);
// Both `v` and `opt_v` refer to the same vector, so the size is the same.
std::cout << "Using a reference to the vector:\n"
<< "Original vector size: " << v.size() << '\n'
<< "Optional vector size: " << opt_v->get().size() << "\n\n";
// Demonstrate a reference to an optional vector
// ---------------------------------------------
// Copy `w` into `opt_w`.
// Changes to `opt_w` have no effect on `w` (and vice versa).
optional_vector opt_w {w};
w.clear();
// A reference to `opt_w` will be used in g(), so `opt_w` is updated.
g(opt_w);
// There are two vectors that now have different sizes.
std::cout << "Using a copy of the vector:\n"
<< "Original vector size: " << w.size() << '\n'
<< "Optional vector size: " << opt_w->size() << '\n';
return 0;
}
这段代码的输出:
Using a reference to the vector:
Original vector size: 1
Optional vector size: 1
Using a copy of the vector:
Original vector size: 0
Optional vector size: 5