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

Posted

技术标签:

【中文标题】我想知道临时对象(name_compare())是按值传递还是通过引用 std::sort【英文标题】:I wonder that if the temporary object(name_compare()) is passed by value or by reference to 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()没有声明,因此它将被移动并按值获取。 我有一个问题要问你。你为什么不接受弗拉德对你刚刚提出的问题的回答?我看到它回答了你的最后一个问题。虽然不接受,但如何等待答复? 【参考方案1】:

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

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

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

但这并不重要,因为

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

在您的情况下,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,它尽可能使用移动构造。 感谢您的澄清。我会深入挖掘。

以上是关于我想知道临时对象(name_compare())是按值传递还是通过引用 std::sort的主要内容,如果未能解决你的问题,请参考以下文章

在这个初始化过程中创建了多少临时对象?

php文件上传时,关于临时目录的问题,我想知道的是,默认路径是C:\WINDOWS\temp,但是后面怎么会多出

临时变量如何在 Worker 上可用

关于mysql建立临时表的问题(新手入门)

使用标准构造函数传递临时对象

传递指向临时对象的指针