我想不是,但是我想确认。有什么用const Foo&&
,Foo
类类型在哪里?
Answers:
它们偶尔有用。C ++ 0x草案本身在几个地方使用了它们,例如:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
上面的两个重载确保另一个ref(T&)
和cref(const T&)
函数不绑定到右值(否则可能会发生)。
更新资料
我刚刚检查了官方标准N3290,不幸的是,该标准尚未公开发布,并且在20.8函数对象[function.objects] / p2中具有:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
然后,我检查了最新的C ++ 11后草案(可公开获得)N3485,并且在20.8函数对象[function.objects] / p2中仍然说:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
const T&&
吗?
const T&&
prevent可以防止某些人愚蠢地使用形式为的显式模板args ref<const A&>(...)
。这不是一个非常强烈的论点,但是const T&&
over的代价T&&
却很小。
获得常量值引用(而不是=delete
)的语义是说:
以下用例可能是恕我直言,非常适合对const进行右值引用,尽管该语言决定不采用这种方法(请参见原始SO post)。
通常建议使用make_unique
和make_shared
,但两者都可以,unique_ptr
并且shared_ptr
可以通过原始指针构造。两个构造函数都按值获取指针并将其复制。两者都允许(即:不阻止)在构造函数中连续使用传递给它们的原始指针。
以下代码使用double free进行编译和结果:
int* ptr = new int(9);
std::unique_ptr<int> p { ptr };
// we forgot that ptr is already being managed
delete ptr;
双方unique_ptr
并shared_ptr
能防止上述,如果他们的相关构造期望得到原始指针作为一个const右值,例如用于unique_ptr
:
unique_ptr(T* const&& p) : ptr{p} {}
在这种情况下,上面的double free代码无法编译,但是以下代码可以:
std::unique_ptr<int> p1 { std::move(ptr) }; // more verbose: user moves ownership
std::unique_ptr<int> p2 { new int(7) }; // ok, rvalue
请注意,ptr
它在移动后仍可以使用,因此潜在的错误并未完全消失。但是,如果要求用户调用std::move
此类错误,则会落入以下通用规则:不要使用已移动的资源。
一个人会问:好,但是为什么要T*
const&& p
?
原因很简单,允许创建unique_ptr
const指针。请记住,const的右值引用不仅仅是更通用的右值引用,因为它同时接受const
和non-const
。因此,我们可以允许以下操作:
int* const ptr = new int(9);
auto p = std::unique_ptr<int> { std::move(ptr) };
如果我们只希望使用rvalue引用,则不会执行此操作(编译错误:无法将const rvalue绑定到rvalue)。
无论如何,现在提出这样的事情为时已晚。但是这个想法确实提出了对const的右值引用的合理用法。
它们是允许的,甚至是基于进行排名的函数const
,但是由于您不能从所引用的const对象移动const Foo&&
,因此它们没有用。
const T&, T&, const T&&, T&&
除了std :: ref之外,标准库还出于相同目的在std :: as_const中使用const rvalue引用。
template <class T>
void as_const(const T&&) = delete;
获取包装值时,它还用作std :: optional中的返回值:
constexpr const T&& operator*() const&&;
constexpr const T&& value() const &&;
以及在std :: get中:
template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
大概是为了在访问包装后的值时保持值的类别以及包装器的恒定性。
这对是否可以在包装的对象上调用const rvalue ref限定函数有所不同。也就是说,我不知道const rvalue ref限定函数的任何用途。
我无法想到这种情况会直接有用,但可能会间接使用:
template<class T>
void f(T const &x) {
cout << "lvalue";
}
template<class T>
void f(T &&x) {
cout << "rvalue";
}
template<class T>
void g(T &x) {
f(T());
}
template<class T>
void h(T const &x) {
g(x);
}
的T IN克为T const的,所以˚F的x是一个常量Ť&&。
可能会导致f发生编译错误(当它尝试移动或使用对象时),但是f可以采用rvalue-ref,这样就不能在不修改rvalue的情况下在lvalues上调用它(如太简单了)以上示例)。
const&&
的很重要,尽管他没有说为什么:youtube.com/watch?