在下面的函数中,我想要一个向量objects
并返回该向量的一个元素的副本。由于下面的代码编译正确,我假设迭代器copy_objects.back()
被自动解除引用。但我不确定。返回声明中发生了什么?
MyObject best(vector<MyObject>& objects) {
vector<MyObject> copy_objects = objects;
sort(copy_objects.begin(), copy_objects.end(), compare_MyObject_func);
return copy_objects.back();
}
我知道还有其他方法可以完成手头的简单任务,但我很想知道这个例子中发生了什么。
后续问题......
使用上面best
函数的定义,我得到以下编译错误:
error: invalid initialization of non-const reference of type ‘std::vector<MyObject>&’ from an rvalue of type ‘std::vector<MyObject>’
bestObject = best(myfunction(objects));
^
相关类型声明的位置为:
MyObject bestObject;
vector<MyObject> objects;
vector<MyObject> myfunction(vector<MyObject>&);
我的直觉告诉我这个错误与上面的原始问题有关。但是,我不明白问题是什么。
答案 0 :(得分:4)
“取消引用”通常是指将一元*
运算符应用于指针或其他迭代器(如*p
)。这个术语令人困惑,因为它与C ++中的引用类型没有任何关系,因此标准委员会正在转而使用“执行间接”。
无论如何,copy_objects.back()
根本不会返回迭代器。它返回对象的引用(实际引用类型)。您可以看到这一点,因为std::vector<T>::back
的返回类型是const_reference
,它是const value_type&
的typedef,其中value_type
是T
。你永远不会“取消引用”引用。如果要从引用中复制,只需将其视为普通对象即可。
int x = 0;
int& y = x;
int z = y;
在此示例中,z
将是x
和y
引用的对象的副本。
除此之外,我建议也按值取值(删除&
):
MyObject best(vector<MyObject> objects) {
sort(objects.begin(), objects.end(), compare_MyObject_func);
return objects.back();
}
无论如何你都要复制它,所以把它作为参考是毫无意义的。特别是非const
引用表明您将修改给定的参数,而不是。实际上,当vector
可以移动到函数中时,参考参数会给您带来更差的性能。参考类型参数永远不会移动。
回答您延伸的问题:
myfunction
按值返回,这意味着它返回的对象是一个临时对象(它是其中任何内容的副本)。您不能将非const
引用(best
的参数)绑定到临时对象。这是有道理的,因为那时临时对象会消失(因为它是临时的)并且引用将留下什么都没有。
如果您将参数类型设为const
引用,那就没问题,因为const
引用会延长临时对象的生命周期。如果您将参数设置为非引用,那么它也可以,因为它将生成临时对象的本地副本。
答案 1 :(得分:2)
back()
不返回迭代器。相反,它返回对向量的最后一个元素的引用。
答案 2 :(得分:1)
您正在执行对象的浅表副本,然后对副本进行排序。 back()
返回对最后一个元素的引用,因此您将从该引用复制到调用者范围内的返回变量。
答案 3 :(得分:1)
您正在传递参考资料 - 因此您可以返回参考资料:
MyObject& best(vector<MyObject>& objects) {
vector<MyObject>::iterator result = objects.begin();
if(result == objects.end()) throw std::runtime_error("Empty");
else {
for(vector<MyObject>::iterator pos = std::next(result);
pos != objects.end();
++pos)
{
// Might be ! compare_MyObject_func
if(compare_MyObject_func(*result, *pos)) result = pos;
}
}
return *result;
}
如果您只对某个元素感兴趣,则无需对任何内容进行排序。
注意:查找某个元素的复杂度为O(n),而排序为O(n log(n))