2013-05-01 13 views
15

std::equal() jest niebezpieczne, ponieważ funkcja nie może wiedzieć, czy przekroczy ona długość drugiego porównywalnego pojemnika. To znaczy:Czy istnieje bezpieczna alternatywa dla std :: equal?

std::vector<int> v(100); 
std::vector<int> w(10); 
bool same = std::equal(v.begin(), v.end(), w.begin()); 

... spowoduje przepełnienie bufora dla w.

Oczywiście możemy przetestować te rzeczy (v.size() == w.size()), ale kompilatory takie jak Visual Studio 2010 nadal zgłaszają samą funkcję jako niebezpieczną. I rzeczywiście jest to niebezpieczne w pewnym fundamentalnym sensie: zespół programistów o różnych poziomach doświadczenia ostatecznie zapomni porównać rozmiary.

Bezpieczna alternatywa jest łatwa do wdrożenia.

template< typename Iter1, typename Iter2 > 
bool equal_safe(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2) 
{ 
    while(begin1 != end1 && begin2 != end2) 
    { 
     if(*begin1 != *begin2) 
     { 
      return false; 
     } 
     ++begin1; 
     ++begin2; 
    } 
    return begin1 == end1 && begin2 == end2; 
} 

Ale czy istnieje bezpieczna alternatywa w standardowej bibliotece?

+2

Bezpieczna alternatywa, aby zrobić dokładnie to, co? Po prostu porównaj dwa 'std :: vector's? Lub dwa zakresy iteracyjne? –

+0

@ftfbit Aby zrobić to, co robi std :: equal(). Aby porównać dwa zakresy iteratorów. – OldPeculier

+1

Łatwo jest napisać implementację safe_equal, jeśli == nie spełnia Twoich wymagań. –

Odpowiedz

17

w C++ 14, biblioteka standardowa zawiera wersję std::equal które ma dwie pary iteratorów, podobne do safe_equal. To samo dotyczy std::mismatch i std::is_permutation.

8

vector ma operatora ==, który najpierw sprawdza rozmiar. W twoim przykładzie użyj warunku v==w.

+0

co oznacza, że ​​jest bezpieczny zgodnie z definicją bezpieczeństwa OP. –

+0

Cóż, myślałem, że było jasne, ale dla przykładu op, "v == w" jest bezpieczne. – huskerchad

+0

@huskerchad Użyłem wektorów jako przykładu, ponieważ można szybko utworzyć dwa o różnych rozmiarach. Ale wyobraź sobie, że jest to lista ... – OldPeculier

1

Ja sam chciałem taką funkcję. Nie mogłem znaleźć żadnych obiektów w standardowej bibliotece.

Jeśli chcesz użyć wzmocnienia. Boost.Range ma równy co moim zdaniem jest to, co szukasz http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/algorithms/non_mutating/equal.html

+1

Wzmocnienie 1.54 (wydane na początku lipca) zawiera cztery wersje iteracyjne równych ',' is_permutation' i 'mismatch'.Możesz pobrać kod z bagażnika doładowania już dziś. –

1

Mam ten sam problem i rozwiązałem go, sprawdzając rozmiar wektora przed równym.

std::vector<int> v(100); 
    std::vector<int> w(10); 
    bool same = (v.size() == w.size()) && std::equal(v.begin(), v.end(), w.begin()); 
0

Można również użyć std::lexicographical_compare dwukrotnie, aby ustalić, czy też sekwencja jest mniejsza od drugiej.

Powiązane problemy