C++ returning reference from function with type of dereferenced type?

China☆狼群 提交于 2020-01-15 04:54:06

问题


In the following function, I want to take a vector objects and return a copy of one of the elements of that vector. Since the code below compiles correctly, I'm assuming that the iterator copy_objects.back() is automatically dereferenced. But I don't know for certain. What is happening in the return statement?

MyObject best(vector<MyObject>& objects) {
    vector<MyObject> copy_objects = objects;
    sort(copy_objects.begin(), copy_objects.end(), compare_MyObject_func);
    return copy_objects.back();
}

I know there are other ways to accomplish the simple task at hand, but I'm curious to know what's going on in this example.


Follow-up question...

Using the definition of the best function above, I get the following compile error:

error: invalid initialization of non-const reference of type ‘std::vector<MyObject>&’ from an rvalue of type ‘std::vector<MyObject>’
     bestObject = best(myfunction(objects));
                                          ^

Where the relevant type declarations are:

MyObject bestObject;
vector<MyObject> objects;
vector<MyObject> myfunction(vector<MyObject>&);

My intuition tells me this error is related to the original question above. But, I don't understand what the problem is.


回答1:


"Dereference" usually refers to applying the unary * operator to a pointer or other iterator (like *p). This terminology is confusing because it doesn't have anything to do with reference types in C++, so the standards committee are moving to use "perform indirection" instead.

Anyway, copy_objects.back() does not return an iterator at all. It returns a reference to the object (an actual reference type). You can see this because the return type for std::vector<T>::back is const_reference which is a typedef for const value_type&, where value_type is T. You don't ever "dereference" references. If you want to copy from a reference, you just need to treat it like a normal object.

int x = 0;
int& y = x;
int z = y;

In this example, z will be a copy of the object referred to by both x and y.


In addition to this, I recommend just taking the argument by value too (remove the &):

MyObject best(vector<MyObject> objects) {
  sort(objects.begin(), objects.end(), compare_MyObject_func);
  return objects.back();
}

You're going to copy it anyway, so taking it by reference is pointless. Especially a non-const reference suggests that you're going to modify the given argument, which you don't. In fact, a reference parameter gives you worse performance when the vector could be moved into the function. The reference type parameter will never move.


Answer to your extended question:

myfunction returns by value, which means that the object it returns is a temporary object (it's a copy of whatever was inside it). You can't bind a non-const reference (the parameter of best) to a temporary object. This makes sense because then the temporary object would disappear (because it's temporary) and the reference would be left referring to nothing.

If you made the parameter type a const reference, it would be fine, because const references extend the lifetime of a temporary object. If you made the parameter a non-reference, it would also be fine, because it would make a local copy of the temporary object.




回答2:


back() does not return an iterator. Instead, it returns a reference to the last element of the vector.




回答3:


You are performing a shallow copy of objects and then sorting the copy. back() returns a reference to the last element, so you are making a copy from that reference into the return variable in the caller's scope.




回答4:


You are passing in a reference - hence you can return a reference:

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;
}

There is not need to sort anything if you are interested in a certain element, only.

Note: the complexity for a lookup of a certain element is O(n), while sorting is O(n log(n))



来源:https://stackoverflow.com/questions/20937611/c-returning-reference-from-function-with-type-of-dereferenced-type

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