c – 如何将指针的关系比较转换为错误?

前端之家收集整理的这篇文章主要介绍了c – 如何将指针的关系比较转换为错误?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们被许多次被以下错误所困扰:
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void print(int* pn) { cout << *pn << " "; }

int main() {
    int* n1 = new int(1);
    int* n2 = new int(2);
    int* n3 = new int(3);

    vector<int*> v;
    v.push_back(n1);
    v.push_back(n2);
    v.push_back(n3);

    sort(v.begin(),v.end());   // Here be dragons!

    for_each(v.begin(),v.end(),print);
    cout << endl;
    delete n1; delete n2; delete n3;
}

问题是std :: sort是比较整数指针而不是整数,这不是程序员的意图.更糟糕的是,输出可能显示正确和确定(考虑新的或在堆栈上分配的地址的顺序).根本的问题是,最终调用operator<对于T,当T是指针类型时,这很少是一个好主意. 有什么办法可以防止这种或至少得到一个编译器警告?例如,有没有办法创建一个自定义版本的std :: sort,当T是一个指针时需要比较功能

解决方法

对于一般的指针,您可以这样做:
#include <ctime>
    #include <vector>
    #include <cstdlib>
    #include <algorithm>
    #include <functional>
    #include <type_traits>

    namespace util {
        struct sort_pointers {
            bool operator() ( int *a,int *b ) {
                return *a < *b;
            }
        };

        template <typename T,bool is_pointer = !std::tr1::is_pointer<T>::value>
        struct sort_helper {
            typedef std::less<T> wont_compare_pointers;
        };

        template <typename T>
        struct sort_helper<T,false> {
        };

        template <typename Iterator>
        void sort( Iterator start,Iterator end )
        {
            std::sort( start,end,sort_helper
                       <
                            typename Iterator::value_type
                       >::wont_compare_pointers() );
        }

        template <typename Iterator,class Func>
        void sort( Iterator start,Iterator end,Func f ) {
            std::sort( start,f );
        }
    }

    int main() {
        std::vector<int> v1;
        std::vector<int*> v2;
        srand(time(0));

        for( int i = 0; i < 10; ++i ) {
            v1.push_back(rand());
        }

        util::sort( v1.begin(),v1.end() );

        for( int i = 0; i < 10; ++i ) {
            v2.push_back(&v1[i]);
        }

        /* util::sort( v2.begin(),v2.end() ); */ //fails.
        util::sort( v2.begin(),v2.end(),util::sort_pointers() );

        return 0;
    }

std :: tr1 :: is_pointer只是在Visual Studio 2008中调用的,但是我认为Boost也有一个,而较新的编译器可能会将它提供为std :: is_pointer.我相信有人能够写一个更漂亮的解决方案,但这似乎是有效的.

但我必须说,我同意齿轮,没有理由,程序员应该能够看到这将是一个问题,并采取相应的行动.

加成:

您可以将其概括一点,我想,要自动选择一个函数,将取消引用指针并比较值:

namespace util {
    template <typename T>
    struct sort_pointers {
        bool operator() ( T a,T b ) {
            return *a < *b;
        }
    };

    template <typename T,bool is_pointer = !std::tr1::is_pointer<T>::value>
    struct sort_helper {
        typedef std::less<T> compare;
    };

    template <typename T>
    struct sort_helper<T,false> {
        typedef sort_pointers<T> compare;
    };

    template <typename Iterator>
    void sort( Iterator start,Iterator end )
    {
        std::sort( start,sort_helper
                   <
                        typename Iterator::value_type
                   >::compare() );
    }
}

这样你不必考虑如果你提供它与指针比较与否,它将自动被整理出来.

猜你在找的C&C++相关文章