에 일시적으로 수정 된 벡터를 통과, 나는 벡터는 각 레벨에서 수정되는 방식으로 함수에 벡터를 통과해야하고 관계없는 코드.되돌아 문제에서 함수
나중에 벡터 수정을 단순화하여 나중에 pop_back 할 필요가없는 방법이 있습니까?
에 일시적으로 수정 된 벡터를 통과, 나는 벡터는 각 레벨에서 수정되는 방식으로 함수에 벡터를 통과해야하고 관계없는 코드.되돌아 문제에서 함수
나중에 벡터 수정을 단순화하여 나중에 pop_back 할 필요가없는 방법이 있습니까?
내가 무엇을해야하는 것은 이미 꽤 읽을는 사실을 알게 될 것입니다. 개선 할 점은 두 가지뿐입니다.
우선, 중복 복사본을 피하고 참조로 벡터를 전달하십시오.
둘째, 백 트랙킹 불변성을 유지하려면 여전히 pop_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;
}
때문에 매우 그것을, 우리는 vec.back()
통화 사이의 정수는 것을 확신 할 수 있습니다 밀어 정수. 따라서 팝과 푸시의 다른 쌍 대신 간단한 할당을 할 수 있습니다.
매번 동일한 벡터로 푸시하고 팝을하려면 함수 인수로 참조를 사용하거나 벡터 변수를 전역으로 정의하는 것이 좋습니다. 이 방법으로, 당신은 많은 기억을 낭비합니다. – Alireza
이 답변은 팝백이 무의미하다는 점을 제외하고는 예외가 아닙니다. – Yakk
@Yakk - 무엇을 던지 느냐에 달려 있습니다. 그것이 단지 벡터라면, RAII popper는 가미 카제의 헬멧입니다. – StoryTeller
당신은 파괴에 당신을 위해 자동으로 pop_back
를 호출하는 가드 클래스를 만들 수 있습니다
template <typename T>
class push_pop_guard
{
private:
std::vector<T>& _v;
public:
template <typename Item>
push_pop_guard(std::vector<T>& v, Item&& x) : _v{v}
{
_v.push_back(std::forward<Item>(x));
}
~push_pop_guard()
{
_v.pop_back();
}
};
사용 예 :
void function(std::vector <int> vec)
{
{
push_pop_guard ppg{vec, 0};
function(vec);
}
// ...
}
While (매우) 차가운, 이것은 무언가에 간단한 불필요한 복잡성을 추가합니다. –
T를 떨어 뜨리고 컨테이너에 C를 추가합니다. C가 추론 될 수 있도록 팩토리 함수를 작성하고이를'auto'로 저장하십시오. – Yakk
왜 downvote? –
당신은 방법에 값을 전달하고 나중에 벡터에 밀어 수 있습니다
void function(std::vector <int> vec, int element){
vec.push_back(element);
//Do stuff
function(vec,0);
function(vec,1);
return;
}
아주 좋습니다! 프로토 타입을 디폴트 값으로'int element = 0'으로 만들 수 있습니다. –
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::optional
은 c++14 및 이전에 boost::optional
로 대체 할 수 있습니다.
scope_guard
이 일반적으로 유용합니다.
나는 또한 참조로 전달하여 값으로 전달되는 vector
을 대체합니다. 훨씬 더 효율적일 수 있습니다. 각 재귀마다 재 할당을 피할 수 있습니다.
연산자 []를 통해 벡터를 수정 하시겠습니까? –
각 호출에서 전체 벡터를 복사 하시겠습니까? – Yakk
@Yakk 메모리 처리가 문제가 발생하는 재귀 수준에서 문제가되지 않기 때문에 값으로 전달하는 것이 컴파일러 최적화로 인해 더 빠를 수 있다고 읽었습니다. – byrass