2

私はmoveセマンティクスの初心者です。このコードは次のとおりです。

template <typename... Args>
void foo(const Args & ... args){
    map<tuple<Args...>, int> cache;
    auto result = cache.emplace(move(make_tuple(args ...)),1);
    //...
    }

以下よりも効率的:

template <typename... Args>
void foo(const Args & ... args){
    map<tuple<Args...>, int> cache;
    tuple<Args...> t(args...);
    auto result = cache.insert(make_pair(t,1));
    //...
    }

特にargs大きなオブジェクトが含まれている場合は?

同じ質問ですが、 (またはstd::vectorは必要ありません)make_pairmake_tuple

4

3 に答える 3

0

初め:

auto result = cache.emplace(move(make_tuple(args ...)),1);

auto result = cache.emplace(make_tuple(args ...),1);

違いはありません。make_tuple(args...)一時的であるため、右辺値参照として渡されます。移動しても何も追加されません。

何か違うだろう

tuple<Args...> t(args...);
auto result = cache.emplace(t, 1);

emplace()左辺値参照を受け取るようになったため、移動コンストラクターの代わりに std::pair のコピー コンストラクターを使用します。

いずれにせよ、大きなデータがいずれかに含まれている場合、args...問題はどこかにあります。現在、すべてargsが左辺値参照として渡されます。

あなたがしたいことは次のとおりです。

template <typename... Args>
void foo(Args && ... args){
    map<tuple<Args...>, int> cache;
    auto result = cache.emplace(make_tuple(forward<Args>(args)...)),1);
    //...
}

に右辺値参照を渡すと、右辺値参照foo()としてforward<Args>(args)...転送されるため、コピーではなく移動になります。左辺値参照で呼び出すfoo()と、左辺値として転送されます。

于 2016-04-30T23:50:47.040 に答える
0
template <typename... Args>
void foo(const Args & ... args){
    map<tuple<Args...>, int> cache;
    auto result = cache.emplace(move(make_tuple(args ...)),1);
    //...
}

このコードはより高速になるはずです。emplaceインプレース構築 (完全転送) を実行します。これにより、構築とコピーの最小数が保証されます。ただし、それらをベンチマークしても害はありません。

一般に、可能な場合は emplace を使用します。それは常により良い選択肢であるべきです。

于 2016-04-28T05:49:03.187 に答える