在 lambda 中使用 std::bind 和 std::unique_ptr
use std::bind in lambda with std::unique_ptr
// By const l-value reference
auto func2 = std::bind([](const std::unique_ptr< std::vector<int> >& pw) // fine
{
std::cout << "size of vector2: " << pw->size() << std::endl;
}, std::make_unique<std::vector<int>>(22, 1));
//By non-const l-value reference
auto func3 = std::bind([](std::unique_ptr< std::vector<int> >& pw) // fine
{
std::cout << "size of vector3: " << pw->size() << std::endl;
}, std::make_unique<std::vector<int>>(22, 1));
// By Value
auto func4 = std::bind([](std::unique_ptr< std::vector<int> > pw) // error
{
std::cout << "size of vector4: " << pw->size() << std::endl;
}, std::make_unique<std::vector<int>>(22, 1));
func4(); // without this line, compilation is fine. The VS generates error for the calling of the bind object.
// By r-value reference
auto func5 = std::bind([](std::unique_ptr< std::vector<int> >&& pw) // error
{
std::cout << "size of vector5: " << pw->size() << std::endl;
}, std::make_unique<std::vector<int>>(22, 1));
func5(); // without this line, compilation is fine.
为什么 func4 和 func5 编译失败?
func4
会产生错误,因为 lambda 的参数是按值传递的。但std::unique_ptr
是不可复制的。
func5
更复杂,我们可以从文档中读取 std::bind:
给定从先前对绑定的调用中获得的对象 g,当它在函数调用表达式
g(u1, u2, ... uM)
中调用时,会发生对存储对象的调用,就像通过std::invoke(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN))
一样,其中fd
是绑定参数的值和类型的值std::decay_t<F>
v1
,v2
, ...,vN
按以下规定确定。
。
普通存储参数arg
作为 lvalue 参数传递给可调用对象:上面 std::invoke 调用中vn
的参数只是 arg,对应的类型Vn
是T cv &
,其中cv与g
的 CV 资格相同。
因此,即使std::make_unique<std::vector<int>>(22, 1)
是 r 值,也会为 lambda 提供 l 值,这与预期的 r 值不兼容。
这也可以解释为什么func3
工作正常。
bind
返回一个可以多次调用的函数对象。
它接受其参数并将其存储在元组(或等效元组)中。 然后,它用其余参数调用第一个参数。 这与 C++17 中的std::invoke
类似。
对于这两种失败的情况,您都无法多次调用 lambda。 因此,当您调用它一次时,您会收到错误,因为bind 假定您希望能够再次调用它。 做任何其他事情都是疯狂的,因为它无法知道你永远不会在它的operator()
的背景下再次调用它。
从逻辑上讲,这些调用应该会失败。 该标准还要求它们失败,因为在这种情况下,标准的行为是合乎逻辑的。
auto funcA =
[pw=std::make_unique<std::vector<int>>(22,1)]
{
std::cout << "size of vector2: " << pw->size() << std::endl;
};
auto funcB =
[pw=std::make_unique<std::vector<int>>(22,1)]() mutable
{
std::cout << "size of vector2: " << pw->size() << std::endl;
};
下面是两种不同的 lambda,它们大致执行您的代码所做的事情。 我们只是捕获,而不是绑定和传递。
在funcA
我们有一个const unique_ptr
,在funcB
我们有一个非const
unique_ptr
。 在第二个中,我们可以移出唯一的 ptr;首先,我们不能。
std::bind
是在 C++ 中存在的 lambda 之前编写的,很少有比使用 lambda 更好的主意。 lambda 中的缺陷大多在 C++14 之前已经消除,并且在极少数情况下使用bind
而不是 lambda 是一个好主意。
std::bind
生成神秘的错误消息,并且在许多极端情况下具有神秘的行为,例如将bind
的结果传递给另一个bind
。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 为什么 std::unique 不调用 std::sort?
- 我对 std::unique(算法)C++有问题
- std::shared_ptr::unique(),复制和线程安全
- 如何在C++03中用自定义谓词调用std::unique
- C++ std::unique并没有显示我对它的期望
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 为什么 [std::unique] 不能应用于 [std::multiset]?
- 使用 std::unique 和 vector.erase 删除除最后一次出现的重复元素之外的所有元素
- 是否可以在 std::unique<T[ ]> 上应用 std::sort?
- std::unique 是否有大小限制
- 从 std::unique 返回的迭代器的用法
- 使 std::unique<T> 与 std::unique<const T, CustomDeleterType 兼容>
- Std::list.unique()应该使迭代器无效
- 无法使用初始化器列表构造 vector<std::unique<...>>
- 从自定义对象- std:unique的向量中消除重复项会导致崩溃
- 我能保证std::unique将保留第一个元素吗?
- 在 std::vector<std::unordered_set上使用 std::unique(<T>>