2016-12-22 3 views
0

Давайте представим, что в массив хранятся некоторые данные, которые должны пройти через функцию, которая принимает вектор. В этой ситуации, очевидно, данные массива должны быть преобразованы в соответствующий векторный тип. Одним общим подходом будетПреобразование массивов в векторы внутри аргумента функции

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

где arr - указанная переменная массива. Я знаю, что мы добавили только одну строку, но она выглядит как ненужное загрязнение кода. Так что я попробовал этот

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

, что работал. Ниже приведен подробный код.

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

От этого, мой первый вопрос: этот подход в порядке или у него есть нежелательное поведение?

После этого я решил изменить аргумент функции принять векторную ссылку как

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

    } 
} 

, что не работает. Здесь ошибка, что я получил

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){ 

Вот второй вопрос: почему, когда аргумент функции, как случайно векторной ссылкой этот подход не работает. Есть ли способ обойти эту ошибку компилятора, поддерживая подход к созданию векторного объекта в функции аргумента или нет?

+2

, как говорится в сообщении компилятора, вы должны сделать ссылку 'const' –

+0

почему его нужно быть постоянным? – Randerson

+3

Если это не const, вы можете изменить параметр в функции, что на самом деле не имеет смысла для временного объекта. Это общий вопрос [см. здесь] (http://stackoverflow.com/questions/13826897/why-not-non-const-reference-to-temporary-objects) –

ответ

1

Проблема связывания rvalue (std::vector<int>(a,a+5) в вызове функции) к lvalue reference (std::vector<int> &vec в списке параметров функции). rvalue может связываться с const lvalue reference, так до тех пор, пока параметр не будет изменен самое простое решение, чтобы написать

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

который, кстати, экономит вам одну операцию копирования на векторе. Или вы можете написать функцию перегрузки привязки явно rvalues с помощью параметра rvalue reference.

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

Но вы должны быть осведомлены о том,, что перегрузка будет только связываются с rvalues. Таким образом, вам нужно будет сохранить две функции: одну для lvalues и одну для rvalues.

Дополнительную информацию можно получить по телефонам lvalues и rvalues, см., Например, Understanding lvalues and rvalues in C and C++ или запросить свою любимую поисковую систему ;-).

1

В этой строке print (std :: vector (a, a + 5)), компилятор создает временный объект, который является ссылкой rvalue. Здесь мы пытаемся передать значение ссылки на функцию, которая принимает NON Const Lvalue ссылку, следовательно, ошибка компилятора. Вместо этого, если вы объявляете метод print() для принятия ссылки на rvalue, вы можете избавиться от ошибки компиляции.Пожалуйста, смотрите фрагмент кода ниже

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

Чем больше на Lvalue, ссылки RValue, пожалуйста, обратитесь http://en.cppreference.com/w/cpp/language/reference

+0

(1) В строке * print (std :: vector (a, a + 5) * компилятор создает 'rvalue', а не' const' (иначе мы не смогли бы перейти к функции, принимающей неконсоль параметр --- как и в вашем решении), а не ссылка. Но у нас есть ссылка в списке параметров. (2) Существует различие между универсальной ссылкой и ссылкой rvalue. Это последняя. [universial-references-in-c11] (https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers) – marlam

+0

@marlam Спасибо за ваши комментарии. Я полностью согласен с вами. – haasi84

Смежные вопросы