Nia*_*all 22 c++ rvalue-reference language-lawyer move-semantics c++11
在上一个问题之后,我一直在研究ref-qualifiers.
给出下面的代码示例;
#include <iostream>
#include <string>
#include <utility>
struct A {
std::string abc = "abc";
std::string& get() & {
std::cout << "get() &" << std::endl;
return abc;
}
std::string get() && {
std::cout << "get() &&" << std::endl;
return std::move(abc);
}
std::string const& get() const & {
std::cout << "get() const &" << std::endl;
return abc;
}
std::string get() const && {
std::cout << "get() const &&" << std::endl;
return abc;
}
};
int main()
{
A a1;
a1.get();
const A a2{};
a2.get();
A().get();
const A a3{};
std::move(a3).get();
}
Run Code Online (Sandbox Code Playgroud)
输出正如您所期望的那样:
get()&
get()const&
get()&&
get()const &&
这用clang和gcc 4.9.1编译并运行(尽管不是4.9.0).现场样品.
在一般代码中(样本可以看到代码如何编译和运行).
const &&
ref-qualifier对方法的目的是什么?该方法无法修改对象上的内容(它是const
),尝试return std::move(abc);
从该const &&
方法实际上根本不移动std::string
.据推测,您可能希望能够修改对象,因为它是一个r值并且不会长时间存在.如果const &&
要删除限定方法,代码std::move(a3).method()
将绑定到const &
限定方法,这是有意义的.
const &
和一个合格的方法之间是const &&
什么?即如何实施变化或为什么你想要两者?std::string
忠实地能够被"搬"出来的临时对象的?std::string get() const &&
在这种情况下,"规范"签名会是什么样的?Nia*_*all 12
关于...的用处const&&
(一般情况下)
const&&
限定符对成员方法的有用性充其量是最小的.不能以与&&
允许修改方法相同的方式修改对象; const
毕竟它(如上所述,mutable
确实改变了这一点).因此,我们无法撕掉它的胆量,因为临时任期正在到期,就像我们想要的类似于正常情况一样move
.
在许多方面,const&&
可以在类型对象const T&&
开始有用的背景下最好地评估其有用性.函数参数有用const T&&
吗?正如这里的另一个答案(对于这个问题)所指出的,它们在声明删除的函数时非常有用,例如在这种情况下
template <class T> void ref (const T&&) = delete;
Run Code Online (Sandbox Code Playgroud)
到明确禁止prvalue和x值值类别类型的对象从与所述功能被使用,并且const T&&
不结合到所有prvalue和x值的对象.
const&&
方法限定符的用处是什么?
值得注意的是,在提案C++库扩展中optional
,第5.3节包含了重载,例如
constexpr T value() const &&;
Run Code Online (Sandbox Code Playgroud)
被限定为const&&
和被指定执行与&&
替代相同的操作.
我能推断出这个案子的原因; 这是为了完整性和正确性.如果在value()
rvalue上调用该方法,则它执行与之相关的相同操作const
.在const
将需要通过移动所包含的对象或使用它的客户端代码来处理.如果存在某个mutable
包含对象的状态,则可以合法地更改该状态.
这可能还有一些优点; 没有特别的顺序......
= delete
禁止方法在prvalues和xvalues上使用.&&
方法相同的操作.这里的建议是从标准库(及其扩展)中排序.对于
const&&
合格的方法,"规范"签名会是什么样的?
由于该方法将执行与该&&
方法相同的操作,我建议签名与签名匹配&&
.
我们可以在文章中找到类似的探索这个问题什么是const rvalue引用有用?并且突出的一个用途是这个例子形成标准库:
template <class T> void ref (const T&&) = delete;
template <class T> void cref (const T&&) = delete;
Run Code Online (Sandbox Code Playgroud)
它完全禁用ref
和cref
rvalues.我们可以在草案C++ 11标准部分20.8
函数对象第2段中找到这些声明.
Scott Meyers 在C++ 11的Universal References中暗示了这种用法:
即使简单地添加const限定符也足以禁用"&&"作为通用引用的解释:
假设我们有一个带有状态的类型mutable
。然后const&&
将允许我们改变该状态,并表明这种改变是安全的。
struct bar;
struct foo {
mutable std::vector<char> state;
operator bar() const&;
operator bar() const&&;
};
Run Code Online (Sandbox Code Playgroud)
const
不是绝对的。
const
除非可变状态,否则为了提取状态而在方法中放弃是不安全的const&&
,因为以这种方式从实际const
对象中提取状态是未定义的行为。