2017-12-10 11 views
2

に一時的に改変ベクターを渡し、私は、ベクターが、各レベルで変更されるように関数にベクトルを渡すために必要なのです無関係なコード。後戻りの問題では機能

私は後でpop_backする必要がないようにベクターの変更を簡略化する方法はありますか?

+0

演算子[]を使用してベクトルを変更しますか? –

+0

各呼び出しでベクター全体がコピーされますか? – Yakk

+0

@ Yakk私は参照渡しに切り替えました。問題は、再帰レベルでメモリ処理が問題ではないため、値が渡されるのはコンパイラの最適化のために速くなる可能性があるためです。 – byrass

答えて

1

私は何を持っていることは、すでにかなり読み取り可能であることを見つけます。私が改善する点は2つだけです。

まず、冗長なコピーを避けて参照によってベクターを渡します。

第2に、バックトラッキング不変量を維持するには、pop_backを維持する必要があります。関数がプッシュされ非常に整数を飛び出すので、我々はvec.back()が呼び出しの間その整数であることは確かかもしれ

void function(std::vector<int> &vec){ 
    vec.push_back(0); // Initial modification 
    function(vec); 
    vec.back() = 1; // Second modification 
    function(vec); 
    vec.pop_back(); // Return to previous state 
    return; 
} 

:しかし、あなたはそれほど厄介な場所に移動することができます。だから、別のペアのポップとプッシュの代わりに単純な割り当てを行うことができます。

+0

毎回同じベクトルにプッシュしてポップする場合は、関数の引数として参照を使用するか、ベクトル変数をグローバルに定義する方がよいでしょう。このようにして、あなたはたくさんの記憶を浪費します。 – Alireza

+0

この回答は、ポップバックが無意味な限り、例外的に安全ではありません。 – Yakk

+0

@ヤク - 何を投げるかによって異なります。それがベクトルだけの場合、RAIIポッパーは神風のヘルメットです。 – StoryTeller

3

あなたは破壊にあなたのために自動的にpop_backを呼び出すガードクラスを作成することができます。

​​

使用例を:

void function(std::vector <int> vec) 
{ 
    { 
     push_pop_guard ppg{vec, 0}; 
     function(vec); 
    } 

    // ... 
} 
+0

While(非常に)クールな、これは単純なものに不必要な複雑さを追加します。 –

+0

私はTを落としてコンテナにCを追加します。私はCを推論することができるようにファクトリ関数を書いて 'auto'として保存します。 – Yakk

+0

なぜdownvote? –

2

あなたはメソッドに値を渡すと、後でベクトルにそれをプッシュすることができます:

void function(std::vector <int> vec, int element){ 
    vec.push_back(element); 
    //Do stuff 
    function(vec,0); 
    function(vec,1); 

    return; 
} 
+1

非常に良い!プロトタイプに、デフォルト値の 'int element = 0'を取らせたいかもしれません。 –

1
template<class F> 
struct scope_guard_t { 
    std::optional<F> f; 
    scope_guard_t(F in):f(std::move(f)) {} 
    scope_guard_t(scope_guard_t&& o): 
    f(std::move(o.f)) 
    { 
    o.clear(); 
    } 
    void abandon() { clear(); } 
    void commit_early() { commit(); clear(); } 
    ~scope_guard_t() { commit(); } 
private: 
    void commit() { if(f) (*f)(); } 
    void clear() { f = std::nullopt; } 
}; 
template<class F> 
scope_guard_t<F> scope_guard(F in) { return {std::move(in)}; } 

template<class C, class T> 
auto temp_push(C& c, T&& t) { 
    c.push_back(std::forward<T>(t)); // do 
    return scope_guard(
    [&]{ c.pop_back(); } // undo 
); 
} 
void function(std::vector <int> vec){ 
    { 
    auto scope = temp_push(vec, 0); 
    function(vec); 
    } 

    { 
    auto scope = temp_push(vec, 1); 
    function(vec); 
    } 
} 

std::optionalboost::optionalにして前に交換することができます。

scope_guardが一般に有用である。

また、私はvectorを参照渡しで値渡しに置き換えます。各再帰のためにそれを再割り当てすることを回避するので、はるかに効率的である可能性があります。