c++ - 从 const 右值移动
问题描述
我遇到了一些在函数参数中使用 const rvalue 引用的代码,std::function
该函数参数在 lambda 中传递。令人困惑的是,它随后std::move
调用了这个传入的参数。像这样的东西:
using CallbackFn = std::function<void()>;
using AnotherCbFn = std::function<void(int)>;
void bar(AnotherCbFn&& cb) {
// doSomething();
}
void foo(CallbackFn const&& cb) {
// Some code
bar([ x = std::move(cb) /* <-- What's this? */](int value){
x();
});
}
void baz() {
foo([](){
// doSomethingMore();
});
}
传入常量值引用然后调用std::move
它们的目的是什么?所以我尝试了一个更简单的代码片段来看看在这种情况下会发生什么
#include <utility>
#include <string>
#include <cstdio>
#include <type_traits>
struct Foo {
Foo() = default;
Foo(Foo&& o) {
str = std::move(o.str); // calls the move assignment operator
std::printf("Other [%s], This [%s]\n", o.str.data(), str.data());
}
Foo(Foo const&& o) {
str = std::move(o.str); // calls the copy assignment operator
std::printf("Other [%s], This [%s]\n", o.str.data(), str.data());
}
private:
std::string str = "foo";
};
template <typename T>
void f(T&& x) {
if constexpr(std::is_const_v<T>) {
std::printf("Const rvalue\n");
auto temp = std::move(x);
} else {
std::printf("non-const rvalue\n");
auto temp = std::move(x);
}
}
Foo const getConstRvalue() {
return Foo();
}
Foo getNonConstRvalue() {
return Foo();
}
int main() {
f(getConstRvalue());
f(getNonConstRvalue());
}
这产生了输出:
Const rvalue
Other [foo], This [foo]
non-const rvalue
Other [], This [foo]
在godbolt(这里)检查组件确认发生了什么。Foo(const&&)
调用 的复制赋值运算符std::string
:
调用 std::__cxx11::basic_string<char, std::char_traits, std::allocator >::operator=(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)
whileFoo(Foo&&)
调用 的移动赋值运算符std::string
:
调用 std::__cxx11::basic_string<char, std::char_traits, std::allocator >::operator=(std::__cxx11::basic_string<char, std::char_traits, std::allocator >&&)
我认为(请纠正我!)const-lvalue 函数参数也可以绑定到 const rvalue 参数(以及非 const rvalue、const lvalue 和 non-const lvalue),这就是为什么在由于Foo(const&&)
const-rvaluestd::string
不能绑定到移动赋值运算符中的非 const rvalue 的情况。
那么,传递 const 右值引用然后调用std::move
它的目的是什么,因为调用std::move
通常意味着在此之后不应该使用该值,在这种情况下,实际上涉及的是副本而不是所需的移动语义?是否有一些微妙的语言机制在起作用?
解决方案
std::move 什么也不移动,它只是将左值(对右值cb的引用)重新解释为您忘记在代码片段中显示的某些bar函数所期望的右值。
我怀疑它看起来像:
void bar(CallbackFn const&& cb) {
...
}
推荐阅读
- c# - 如何使用新版本更新 VSTO excel 加载项?
- azure - 我如何决定是否应该使用 Power BI API 将数据推送到我的流数据集或 Azure 流分析?
- python - 检查2个列表是否具有相同的值或值,索引
- python - 在 Python 中打开 excel 文件时出现 Unicode 错误
- javascript - node.js 我需要能够创建一个全新的 JSON 文件
- css - 如何将图像与简单文本并排放置在中心?
- python - scipy.optimize.curve_fit,不支持的操作数类型
- sql - 根据 pyspark 数据框中其他列的值计数聚合一列
- docker - 谷歌云 docker 镜像文件被删除
- r - 基于存储在变量中的“名称”以编程方式调用 Object