configure the compare function to work with std::sort

好久不见. 提交于 2019-12-12 02:08:50

问题


Suppose I have the following snippets:

int compareFoo(std::string** a, std::string** b) {
    return (**a).compare(**b);
}

int main() {
    std::string** foo = new std::string*[3];
    foo[0] = new std::string("a");
    foo[1] = new std::string("c");
    foo[2] = new std::string("b");
    sort(foo,foo+3,compareFoo);
    for (int i = 0; i < 3; i++) {
        std::cout << *foo[i] << std::endl; // print acb
    }
}

If I'd left out the third parameter(compare) for sort, it'd have given me the sorted 3 strings in terms of their memory addresses, that's not how I intended it. But how do I parameterize the compareFoo function so that it won't compare the memory addresses.

void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

The description of Sort on cplusplus.com is quite vague and the given example is simple. Since it takes an Iterator, does it mean that i only work with stand containers? Thank you


回答1:


The comparison function takes two items to compare and returns true if the first one is less than the second one. In your case, it would work like this:

#include <string>
#include <algorithm>
#include <iostream>

using std::sort;

bool compareFoo(std::string* a,std::string* b){
  return *a < *b;
}

int main(){
  std::string** foo = new std::string*[3];
  foo[0] = new std::string("a");
  foo[1] = new std::string("c");
  foo[2] = new std::string("b");
  sort(foo,foo+3,compareFoo);
  for(int i=0;i<3;i++){
    std::cout << *foo[i] << std::endl; 
  }

  // Remember to delete things that you dynamically allocate.
  delete foo[0];
  delete foo[1];
  delete foo[2];
  delete [] foo;
}



回答2:


I'd reconsider whether all of this pointer manipulation is really what you want. This isn't Java or C#. In C++, you do not allocate from the free store ("the heap") by default. Just create your array automatically and store the strings directly. In other words, you'd end up with something like this:

#include <algorithm>
#include <string>
int main(){
    std::string foo [] = {
        "a",
        "c",
        "b"
    };
    std::sort(foo, foo + 3);
    for(int i = 0; i < 3; i++){
        std::cout << foo[i] << '\n'; // print abc
    }
}

Compared to your version, this

  • Is faster
  • Uses less memory (no extra pointer overhead)
  • Doesn't leak memory
  • Is more readable to people familiar with C++
  • Removes any fears about possible null pointers
  • Requires less code
  • Works better with optimizing compilers



回答3:


std::sort takes in 3 things:

  1. A random access iterator representing the start
  2. A random access iterator representing the end
  3. A function that takes in two things and compares them to return their result

So this means it can work with anything that follows the random access iterator template. Namely pointers, so arrays should work just fine.

However with your current code, your dereferencing one level too far, try this

#include <string>
#include <algorithm>
#include <iostream>

using std::sort;

bool compareFoo(std::string a,std::string b){
  return *a < *b; //note the difference
}

int main(){
  std::string* foo = new std::string[3];
  foo[0] = std::string("a");
  foo[1] = std::string("c");
  foo[2] = std::string("b");
  sort(foo,foo+3,compareFoo);
  for(int i=0;i<3;i++){
    std::cout << *foo[i] << std::endl;
  }
}

Note however that in this case we don't need to provide the compare function, the function will automatically use the < operator




回答4:


bool compareFoo(std::string * lhs, std::string * rhs)
{
    return *lhs < *rhs;
}

Since it takes an Iterator, does it mean that i only work with stand containers?

No. Iterator is a concept. A pointer meets the requirements of the iterator concept, and so it is an iterator.



来源:https://stackoverflow.com/questions/12558792/configure-the-compare-function-to-work-with-stdsort

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!