【问题标题】:I wonder that if the temporary object(name_compare()) is passed by value or by reference to std::sort我想知道临时对象(name_compare())是按值传递还是通过引用 std::sort
【发布时间】:2020-05-23 10:13:46
【问题描述】:

我想知道临时对象(name_compare()) 是按值传递还是通过引用 std::sort 传递。

如果您能提供有关此问题的任何提示,我将不胜感激。

 struct Record {
        string name;
        // ...
    };
    struct name_compare {   // compare Records using "name" as the key
        bool operator()(const Record& a, const Record& b) const
            { return a.name<b.name; }
    };
    void f(vector<Record>& vs)
    {
        sort(vs.begin(), vs.end(), name_compare());
        // ...
    }  

【问题讨论】:

  • 你需要看看std::sort是如何声明的。它声明参数是值还是引用?
  • 请告诉我们为什么你想知道?是否有一个潜在的问题让你问这个问题?根本问题是什么?请始终直接询问这些问题。
  • std::sort() 的版本,它接受三个参数,由一对指定范围的迭代器和一个比较器按值接受所有三个参数。
  • 要通过引用传递你必须有一个声明的对象,这里name_compare()没有声明,因此它将被移动并按值获取。
  • 我有一个问题要问你。你为什么不接受弗拉德对你刚刚提出的问题的回答?我看到它回答了你的最后一个问题。虽然不接受,但如何等待答复?

标签: c++ c++11 c++17 function-object


【解决方案1】:

std::sort 推导出Compare 类型并按值接受它:

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

在大多数情况下,这意味着按值接受比较器。

但这并不重要,因为

  1. 比较器通常是一个空对象,只有一个 operator(),因此传递它实际上是一个空操作;
  2. 编译器可以完全优化掉临时对象的创建;
  3. 即使它不是空的,复制一个对象一次对于随后的排序操作来说也是微不足道的

在您的情况下,struct name_compare 没有成员,空对象也是如此。

可以通过将比较器类型包装在std::ref 中来强制推断比较器类型作为参考。

顺便说一句,比较器不一定是类,它也可以是 staticfriend 函数:

struct Record {
    string name;
    static bool compare(const Record& a, const Record& b) {
        return a.name < b.name;
    }
    void f(vector<Record>& vs) {
        sort(vs.begin(), vs.end(), Record::compare);
    }
};

但更好的是,您可以依赖内置的 std::less 实现并为您的类型简单地定义 operator&lt;

struct Record {
    string name;
    bool operator< (const Record& that) const {
        return name < that.name;
    }
    void f(vector<Record>& vs) {
        sort(vs.begin(), vs.end()); // operator < is used automatically
    }
};

【讨论】:

  • 以这种方式定义 op&lt; 可能是错误的。尽管如此,这是一个我们不能立即拒绝的选择。顺便说一句,如果它实际上是不可复制的,std::ref() 会来救援。
  • @rustyx 既然你的回答,我可以得出结论,它需要在std::sort 中调用struct Record 的默认复制构造函数。对吗?
  • std::sort 使用std::swap,它尽可能使用移动构造。
  • 感谢您的澄清。我会深入挖掘。
猜你喜欢
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2019-03-02
  • 2023-04-07
相关资源
最近更新 更多