0

Let's imagine that there is some data stored into an array that needs to go through a function that accepts vector. In this situation, clearly the array data needs to be converted into the respective vector type. One general approach would be

std::vector<int> vec(arr, arr+n);
function(vec);

where arr is the mentioned array variable. I know that we added just one line, but its looks somehow as an unnecessary code pollution. So I tried this

function(std::vector<int>(arr, arr+n))

what worked. Bellow there is a detailed code this.

#include <vector>
#include <iostream>

void print(std::vector<int> vec){
    for(unsigned int i=0; i!=vec.size(); ++i){
        std::cout << vec[i] << std::endl;

    }
}

int main(){
    int a[] = {2,1,4,5,6};
    print(std::vector<int>(a,a+5));
}

From this, my first question is: This approach is ok, or it has some undesired behavior?

After that, I decided to change the function argument to accept a vector reference like

void print(std::vector<int> &vec){
    for(unsigned int i=0; i!=vec.size(); ++i){
        std::cout << vec[i] << std::endl;

    }
}

what did not work. Here is the error that I got

test.cpp: In function ‘int main()’:
test.cpp:13:34: error: invalid initialization of non-const reference of type ‘std::vector<int>&’ from an rvalue of type ‘std::vector<int>’
     print(std::vector<int>(a,a+5));
                                  ^
test.cpp:4:6: error: in passing argument 1 of ‘void print(std::vector<int>&)’
 void print(std::vector<int> &vec){

Here is the second question: Why, when the function argument as chanced to a vector reference this approach did not work. There is someway to get around this compiler error keeping the approach of creating the vector object in the argument function or not?

Randerson
  • 775
  • 1
  • 5
  • 19
  • 2
    as the compiler message says, you have to make the reference `const` – Karsten Koop Dec 22 '16 at 13:06
  • why its need to be constant? – Randerson Dec 22 '16 at 13:08
  • 3
    If it's not const, you could change the parameter in the function, which doesn't really make sense for a temporary object. This is a common question, [see e.g. here](http://stackoverflow.com/questions/13826897/why-not-non-const-reference-to-temporary-objects) – Karsten Koop Dec 22 '16 at 13:10
  • 1
    To expand on what Karsten said: If the function make changes to the vector (eg increment all the values), you probably want those changes reflected in the calling code. C++ forbids binding a non-const reference to a temporary to prevent those surprises. If the function promises it is not going to change the vector (by taking it by const reference), then a temporary is fine. – Martin Bonner supports Monica Dec 22 '16 at 13:20
  • Thanks!!! I will read the tread indicated by @KarstenKoop. In fact, I did not know for what subject should a look for. – Randerson Dec 22 '16 at 13:24

2 Answers2

1

The problem is binding a rvalue (std::vector<int>(a,a+5) in the function call) to a lvalue reference (std::vector<int> &vec in the parameter list of the function). A rvalue can bind to a const lvalue reference, so as long as the parameter will not be changed the simplest solution is to write

void print(const std::vector<int> &vec)

which by the way saves you one copy operation on the vector. Or you could write a function overload binding explicitly to rvalues by having a rvalue reference parameter.

void print(std::vector<int>&& vec)

But you have to be aware of the fact, that this overload will only bind to rvalues. So you will have to maintain two functions, one for lvalues and one for rvalues.

For further reference on lvalues and rvalues, see for example Understanding lvalues and rvalues in C and C++ or ask your favourite search engine ;-).

marlam
  • 590
  • 5
  • 14
1

In this line print(std::vector(a, a+5)), the compiler creates a temporary object which is a rvalue reference. Here we are trying to pass a reference value to a function which accepts non const lvalue reference, hence the compiler error. Instead if you declare print() method to accept a rvalue reference then you can get rid of the compilation error. Please see the code snippet below

#include <vector>
#include <iostream>

void print(std::vector<int> && vec) {
   for(unsigned int i=0; i != vec.size(); ++i) {
      std::cout << vec[i] << std::endl;
   }
}

int main() {
    int a[] = {2,1,4,5,6};
    print(std::vector<int>(a,a+5));
}

The more on lvalue, rvalue reference, please refer http://en.cppreference.com/w/cpp/language/reference

haasi84
  • 104
  • 3
  • (1) In the line *print(std::vector(a,a+5)* the compiler creates an `rvalue`, not `const` (otherwise we could not pass to a function taking a non-`const` parameter --- as you do in your solution) and not a reference. But we have a reference in the parameter list. (2) There is a difference between an universal reference and a rvalue reference. This is the latter. See for example [universial-references-in-c11](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers) – marlam Dec 22 '16 at 19:29
  • @marlam Thanks for your comments. I totally agree with you. – haasi84 Dec 23 '16 at 03:03