我想知道临时对象(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
中来强制推断比较器类型作为参考。
顺便说一句,比较器不一定是类,它也可以是 static
或 friend
函数:
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<
:
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<
可能是错误的。尽管如此,这是一个我们不能立即拒绝的选择。顺便说一句,如果它实际上是不可复制的,std::ref()
会来救援。
@rustyx 既然你的回答,我可以得出结论,它需要在std::sort
中调用struct Record
的默认复制构造函数。对吗?
std::sort
使用std::swap
,它尽可能使用移动构造。
感谢您的澄清。我会深入挖掘。以上是关于我想知道临时对象(name_compare())是按值传递还是通过引用 std::sort的主要内容,如果未能解决你的问题,请参考以下文章