当前位置: 华文星空 > 知识

C++中的std::move函数到底是做什么的?

2021-06-25知识

没有了。 move 就是做类型转换的,把指代对象的左值表达式变成亡值。

move 单独出现没有意义,本身不会对对象做任何事。它可以有意义的场景是可能涉及函数调用的情况(如直接的函数调用、变量初始化、调用运算符等)。

此时它的意义是使外面的函数调用选择接受右值的版本,实际的移动工作是由外面的函数进行的,对象不该使用的情况也是限于被该函数移动后,像题目里描述的单纯引用绑定与此无关。

可以认为这里的「使用」指的是「任何依赖对象需要有某种符合期待的值」的操作(在不确定的值上调用这些操作可能始终合法,但也可能导致错误的业务逻辑),但不指对它赋值之类的「不依赖对象的旧值并只会使之拥有确定的新值」的操作。因为标准库设计是大多数具备移动语义的类型被移动后处于合法但未指定的状态。

有些人说到函数命名…

我们可以注意到 C++ 标准库里这些函数模板照原样返回参数所引用的对象,做的事情只有显式转型,如将它们从左值变成右值或者加上 const 限定(这些函数都是单独出现时无意义,仅在涉及外面的操作时才有意义):

  • move
  • forward
  • move_if_noexcept
  • as_const
  • identity::operator() (此函数本身无直接使用的必要,主要用于 ranges 算法的维持参数原状的默认投影操作。)
  • 这里 move move_if_noexcept 的名字所表示的并非它们本身的作用,而是「对外面的函数调用优先选择的操作」。诚然,这种名称设计给不少人带来了误解,也和后续命名风格不一致。

    (这些名字中 move 是最早定下来的,在 2002 年的提案 WG21-N1377 中就出现了。 move_if_noexcept 出现较晚,名字设计只是为了和 move 一致。)

    有人说到变量名…

    变量名作为表达式都是左值这点是值得记下来的。

    不过…其实上面那些函数都包含「擦掉变量名」的作用,而「是否作为变量名」有显著影响的地方更多在于 decltype ,和这个问题大概关系不大?