当函数可以更改数组时,为什么函数不能更改矢量?

时间:2018-12-04 00:27:48

标签: c++ arrays vector

为了解决问题及其整体利益,我正在尝试从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:当我在LF内部调用LF1时,它返回相同的数组而不旋转,但是当我在LF内部编写LF1的代码时,它似乎在旋转。

问题2: PrintArray()仅在从LF1()调用时或在写入代码后紧接其代码(而不是在LF()中调用LF1())时才打印旋转数组。它打印d次。 d是所需的旋转。

1 个答案:

答案 0 :(得分:1)

关于您在做什么错...您正在按值传递向量 。当您将整数作为值传递时,您不希望更改整数会在调用方中影响它。

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引用传递,例如const vector<int> &A(例如,这就是您的PrintArray()应该使用的)。

您可能不希望现在就过于依赖引用的细节,除了将其视为“一种方便的指针,您不必在所有要取消引用的位置加上* ”。但是,如果您想了解更多具体信息:

What are the differences between a pointer variable and a reference variable in C++?

  

即使此逻辑适用于数组,我在这里也遇到了一些问题。

这可能是您困惑的根源。这是因为C样式的数组会在幕后衰减为指针:

Passing an Array by reference in 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