Почему функции не могут изменять векторы, когда они могут изменять массивы? - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь перейти от массивов к векторам в cpp для решения проблем и их общих преимуществ.Здесь я сталкиваюсь с некоторыми проблемами, хотя эта логика работает с массивами.

#include <iostream>
#include <vector>      
using namespace std;

void PrintArray(vector<int> v) { // O(n)
    for (int i=0; i<v.size(); i++)
        cout << v[i] << " ";
    cout << endl;
}

void LF1(vector<int> A) { // O(n)
    int temp = A[0],i;
    for (i=0; i<A.size()-1; i++)
        A.at(i) = A.at(i+1);
    A.at(i)=temp;
    // PrintArray(A); <-- shows updated array here
}

void LF(vector<int> A, int d) {
    d = d % (A.size());
    cout << "d%n: " << d << endl;
    for (int j=0; j<d; j++)
        LF1(A);
    PrintArray(A);
}

int main(int argc, char const *argv[]) {    
    vector<int> A;
    int d;
    for(int i=1; i<6; i++)
        A.push_back(i);
    PrintArray(A);
    cout << "Enter number of Left rotations to perform : ";
    cin >> d;
    LF(A,d);
    return 0;
}

Проблема 1: Когда я вызываю LF1 внутри LF, он возвращает тот же массив без вращения, но когда я пишу код для LF1 внутри LF, кажется, что он вращается.

Проблема 2: PrintArray () печатает повернутый массив только при вызове из LF1 () или сразу после его кода при записи (вместо вызова LF1 ()) в LF ()когда заставляет его печатать массив d раз.Где d - требуемые повороты.

1 Ответ

0 голосов
/ 05 декабря 2018

Что касается того, что вы делаете неправильно ... вы передаете векторы на значение .Вы не ожидаете, что изменения целого числа повлияют на него в вызывающей программе, когда вы передадите его как значение ...

void SomeFunction(int i) {
    i = i + 1;
    printf("Inside SomeFunction %d\n", i); // changed, 11
}

int i = 10;
SomeFunction(i);
printf("Outside SomeFunction %d\n", i); // unchanged, 10

... если вы хотите увидеть изменение, вам нужно будет передатьуказатель, такой как int *pi, а затем обновить его как *pi = *pi + 1;

Тот же принцип применяется к векторам и другим классам C ++. Если вы просто передадите его как значение,весь вектор копируется.(Ну, если это необходимо, временный объект можно просто использовать повторно).Но пока думайте об этом, как о копируемом: точно так же, как существует разница между передачей целого числа и указателя на целое, существует различие между вектором и указателем на вектор.

Вы можете передать указатель на вектор, если намереваетесь изменить его ... или ... C ++ предлагает другой инструмент, называемый reference , где ссылки очень похожи на указатели, но с некоторыми отличиями.Если вы просто изменили свои аргументы на vector<int> &A, тогда ваш код должен работать, потому что массивы будут «передаваться по ссылке», а не копироваться, когда они «передаются по значению», поэтому изменения вступят в силу.Если вы не хотите, чтобы функция должна была иметь возможность изменять массив, но все же хотите избежать копирования, передайте константную ссылку, например, const vector<int> &A (например, это то, что должен использовать ваш PrintArray ()).

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

Каковы различия между переменной-указателем и ссылочной переменной в C ++?

Я сталкиваюсь с некоторымивопросы здесь , хотя эта логика работает с массивами .

И это, вероятно, источник вашей путаницы.Это происходит из-за того, что массивы в стиле C распадаются на указатели под капотом:

Передача массива по ссылке в C

Я думаю, что это разумнобыть сбитым с толку, учитывая, что другие типы (такие как целые числа и векторы) этого не делают.Это просто причуда C, которую C ++ унаследовал.Поэтому, когда C ++ 11 захотел это исправить, был введен класс-оболочка std :: array:

https://embeddedartistry.com/blog/2017/6/28/an-introduction-to-stdarray https://en.cppreference.com/w/cpp/container/array

Но в C ++ также есть алгоритмчтобы сделать вращение ...

Так что, если вы хотите увидеть хороший пример того, как это будет сделано, это место для начала:

#include <vector>
#include <iostream>
#include <algorithm>

int main() {
    std::vector<int> v{1, 2, 3, 4}; 
    std::rotate(v.begin(), v.begin() + 1, v.end());
    for (auto &i : v)
        std::cout << i << " ";
    std::cout << "\n";
}

Это даст вам 2 3 4 1,В документации есть другие примеры, прочитанные:

https://en.cppreference.com/w/cpp/algorithm/rotate

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...