下面
https://youtu.be/dTeKf5Oek2c?t=2939
Stephen T. Lavavej在一次谈话中说const auto &&
没用。
以下是否有效用例?
NonMovableNonCopyable create () {
// ...
return {};
}
const auto && obj = create ();
具体应用:在XLL代码中,MS Excel通常不喜欢它复制或移动的xloper
,因为复制或移动后它将无法正确释放它们。
答案 0 :(得分:1)
Const T &&
具有可变字段,则 T
非常有用。一个常见的例子是bool m_movedFrom
,它被初始化为false,并在移动时被设置为true。这允许你的对象的其余部分 - 例如 - 资源句柄 - 保持为const。
class Resource // use this as a base class of const correct classes
{
private:
mutable bool m_movedFrom;
protected:
Resource()
: m_movedFrom(false)
{
}
Resource(const Resource&& other)
: m_movedFrom(false)
{
other.m_movedFrom = true;
}
bool isOwning() const // call from descendant's destructor
{
return m_movedFrom;
}
};
编辑:一个更复杂的例子,说明对象本身何时是const,但是全局状态不是(不是声称这是解决此问题的好方法,仅用于说明目的):
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef std::string object_type;
typedef std::string seek_type;
class GoalSeeker
{
private:
static std::vector<const GoalSeeker*> s_store;
const std::vector<const GoalSeeker*>::iterator m_iter;
const object_type m_data;
public:
GoalSeeker( const object_type& data )
: m_iter( s_store.insert( s_store.end(), this ) ), m_data(data)
{
}
GoalSeeker( const GoalSeeker& ) = delete;
GoalSeeker( const GoalSeeker&& other )
: m_iter( other.m_iter ), m_data( other.m_data )
{
*m_iter = this;
}
~GoalSeeker()
{
if( *m_iter == this )
{
// cleanup m_data
}
}
static bool seek( const seek_type& needle )
{
return std::find_if(s_store.begin(), s_store.end(),
[&needle](const GoalSeeker* haystack)
{
return haystack->m_data.find(needle) != std::string::npos;
}) != s_store.end();
}
};
std::vector<const GoalSeeker*> GoalSeeker::s_store = {};
GoalSeeker fn()
{
return GoalSeeker("def");
}
int main() {
GoalSeeker a( "abc" );
GoalSeeker b( "cde" );
GoalSeeker s( (const GoalSeeker&&) fn() );
std::cout << GoalSeeker::seek( "de" ) << " " << GoalSeeker::seek( "fff" );
}
答案 1 :(得分:0)
而不是
const auto && obj = create ();
...只写
const auto object = create();
......或
const auto object{ create() };
=
依赖于编译器忽略复制构造函数调用,但我不知道任何现存的编译器都没有这样做。
获得的清晰度是IMO比参考提供的保证更重要(如果使用参考,请使用普通的&
参考)。也就是说,避免让维护程序员在试图理解参考的基本原理上浪费时间。如果类型是明确指定的,那么可能是多态引用的情况,Petru Marginean的伎俩,但auto
不可能,所以维护程序员不得不摸不着头脑,在一段有偿时间内。
另一方面,const T&&
可以用于函数重载作为参数类型来捕获临时参数的情况,与成员函数的&&
限定符被充分考虑的方式相同在标准中有用。例如,即使我不建议这样做,如果存储了指向实际参数的指针以供以后使用,那么可能有人不希望存储指向临时的指针,这将最终作为悬空指针:
struct Expr{ virtual ~Expr(){} };
struct Sum_expr: Expr
{
const Expr* a_;
const Expr* b_;
Sum_expr( Expr const& a,Expr const& b ): a_( &a ), b_( &b ) {}
template< class A >
Sum_expr( A&&, Expr const&& b ) = delete;
template< class B >
Sum_expr( Expr const&& a, B&& ) = delete;
};
auto main()
-> int
{
Expr a;
Expr b;
Sum_expr sum{ a, b };
Sum_expr sum2{ a, Expr() }; //! Nope, won't compile.
}
注意:A&&
和B&&
支持rvalue和lvalue实际参数,即它们不一定是rvalue引用,因为它们是通用引用
但是我没有重载和区分这些情况,我认为我将这个形式的参数作为一个指针,即使技术上指针可能是一个空指针,因为正如我所看到的那样,我习以为常,它更清楚地传达了意图。
Sum_expr( Expr const* a, Expr const* b );