在前面的一个问题之后,我对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();
}
输出与您预期的一样:
get()(&S;
get()常量(&P;
获取()&&
get()常量(&&)
这将编译并使用clang和GCC4.9.1(但不是4.9.0)运行。 活体样本在这里。
在一般代码中(示例是为了查看代码是如何编译和运行的)。
常量&
引用限定符的用途是什么?该方法无法修改对象上的内容(它是const
),尝试从const&
方法返回std::move(abc);实际上根本不会移动std::string
。 假设您希望能够修改该对象,因为它是一个r值,并且不会存在太久。 如果要删除const&
限定方法,则代码std::move(a3).method()
将绑定到const&
限定方法,这是有意义的。
const&
的方法和限定为const&
的方法之间隐含的语义差异是什么(如果有的话)? 即。 实现会有什么变化,或者为什么同时需要?std::string
真的能够从临时对象中“移”出来吗?std::string get()const&
的“规范”签名是什么样子的?
关于const&&
.。。 (一般)
成员方法上的const&&
限定符的用处最小。 修改对象的方式不能与&&
方法允许修改对象的方式相同; 毕竟,它是const
(如前所述,mutable
确实改变了这一点)。 因此,我们将无法撕开它的内脏,因为临时文件无论如何都将到期,就像我们在类似于正常的移动
的情况下一样。
在许多方面,const&
的有用性可以在const&
类型的对象的有用性的上下文中进行最佳评估。 常量&&
函数参数有多有用? 正如在这里(对这个问题)的另一个回答中指出的,它们在声明删除的函数时非常有用,例如在这种情况下
template <class T> void ref (const T&&) = delete;
要显式禁止prvalue和xvalue值类别类型的对象与函数一起使用,常量T&&
确实绑定到所有prvalue和xvalue对象。
const&&
方法限定符有什么用处?
有趣的是,在C++库扩展的建议中,可选
,§5.3,包含了重载,例如。
constexpr T value() const &&;
它们被限定为const&&
,并被指定为执行与&&
备选项相同的操作。
我能推断出这个案子的原因; 这是为了完整和正确。 如果对rvalue调用value()
方法,则它执行相同的操作,而不依赖于它是否为const
。 常量
将需要被移动的包含对象或使用它的客户端代码来处理。 如果包含对象时存在某种mutable
状态,则可以合法地更改该状态。
这样做很可能还是有一些好处的; 不分先后。。。
=delete
禁止在prvalues和xvalues上使用该方法。&&
方法相同的操作。 这里的建议是来自标准库(及其扩展)的排序。const&&
限定方法的“规范”签名是什么样子的?
由于该方法将执行与&&
方法相同的操作,我建议签名与&&
签名匹配。
我们可以在文章What are constrvalue references good for? 其中一个突出的用法是标准库中的这个例子:
template <class T> void ref (const T&&) = delete;
template <class T> void cref (const T&&) = delete;
它完全禁用rvalues的ref
和cref
。 我们可以在C++11标准草案部分20.8
函数对象第2段中找到这些声明。
ScottMeyers在C++11的通用引用中提到了这个用法:
即使简单地添加一个常量限定符,也足以禁止将“&&"解释为一个通用引用:
假设我们有一个具有mutable
状态的类型。 则const&&
将允许我们改变该状态,并指示这种改变是安全的。
struct bar;
struct foo {
mutable std::vector<char> state;
operator bar() const&;
operator bar() const&&;
};
常量
不是绝对的。
除可变状态外,在const&
方法中丢弃const
以提取状态是不安全的,因为以这种方式从实际的const
对象中提取状态是未定义的行为。