2016-07-05 13 views
-2

ここconst auto &&は本当に役に立たないですか?

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

スティーブンT. Lavavejはconst auto &&が有用ではない話で述べています。

以下は有効なユースケースではありませんか?

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

const auto && obj = create(); 

コンクリート用途:コピーまたは移動した後、正しくそれらを解放することができませんので、XLLコードでは、MS Excelは、一般的に、コピーされたか、それが返す移動するために、そのxloperのが好きではありません。

+3

あなたは 'const auto&'で全く同じことを達成できます。 – StoryTeller

+2

ご希望の時にYouTubeのビデオを右クリックし、「現時点でビデオURLをコピーする」を選択すると、その時間に直接リンクすることができます:https://youtu.be/dTeKf5Oek2c?t=2937 – Tas

+3

おそらくなぜ 'const auto &&'がなぜ問題の本体で役に立たないと思われるのかを説明するでしょう。 – juanchopanza

答えて

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; 
    } 
}; 

EDIT:

#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"); 
} 
:オブジェクト自体がconstのですが、世界的な状態ではない場合を説明するより複雑な例は、(これはこの問題を解決するための良い方法であると主張していない、それだけでイラスト目的のためです)代わりに

const auto && obj = create(); 

+1

私はあなたがここで意味を理解しているか分かりません。私は私には分かりません。あなたは具体的な例を教えてください。 –

+0

例を示すために編集しました。 – lorro

+0

さて、あなたが使っているコードでは、 'const T'を返すC++ 11の関数があります。それは良い考えではない*。推測すると、かつてC + + 03のために提唱していたScott Meyersの古いC++ 11以前のものを読み込んでいたからです。可能性のあるシナリオを検討するときに私の心の中にポップアップしてしまうのは珍しいことです。だから、 'const &&'は完全に意味をなさない。 –

0

...ちょうど

const auto object = create(); 
を書きます

...または

const auto object{ create() }; 

=はコピーコンストラクタ呼び出しをelidingコンパイラに依存しているが、私はそれを行うに失敗した任意の現存コンパイラのことは知りません。

得られた明瞭さは、参照によって提供される保証よりもはるかに重要です(参照を使用する場合、通常の&参照を使用してください)。つまり、メンテナンスプログラマーが参照の根拠を理解しようとするのに時間を浪費することを避けることができます。型が明示的に指定されていれば、多形参照の場合がありますが、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&&サポート右辺と左辺値実引数の両方、彼らは普遍的な参照だからすなわち、それらは、必ずしも右辺値参照はありません。

しかし、オーバーロードして区別するのではなく、私が慣れ親しんだことで、ポインタが技術的にnullpointerになる可能性があるとしても、仮引数をポインタにすると思います。意図をより明確に伝えます。

Sum_expr(Expr const* a, Expr const* b); 
関連する問題