const auto&&真的没用吗?

时间:2016-07-05 07:23:05

标签: c++ const rvalue-reference

下面

https://youtu.be/dTeKf5Oek2c?t=2939

Stephen T. Lavavej在一次谈话中说const auto &&没用。

以下是否有效用例?

NonMovableNonCopyable create () {
   // ...
   return {};
}

const auto && obj = create ();

具体应用:在XLL代码中,MS Excel通常不喜欢它复制或移动的xloper,因为复制或移动后它将无法正确释放它们。

2 个答案:

答案 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 );