【问题标题】:Why can't functions change vectors when they can change arrays?为什么函数可以改变数组却不能改变向量?
【发布时间】:2018-12-04 00:27:48
【问题描述】:

我正在尝试在 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 是所需的旋转次数。

【问题讨论】:

  • 您正在按值传递参数。该函数对参数的副本进行操作;论点保持不变。您的功能是精心设计的无操作。在您最喜欢的 C++ 教科书中阅读有关通过引用传递的内容。
  • 欢迎来到 StackOverflow。你的问题还不错(我不这么认为)......而且考虑到 C 的 unusual array-decaying-behavior,这是一个合理的混淆。但这仍然是一个相当 基本 的问题......所以投票者可能认为阅读基础书籍比在 StackOverflow 上反复试验更好。这是有道理的,所以不要害怕阅读一本书,there are some good ones

标签: c++ arrays vector


【解决方案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&lt;int&gt; &amp;A,那么您的代码应该可以工作,因为数组将“通过引用传递”而不是在“按值传递”时被复制,因此更改会生效。如果您不希望函数需要能够修改数组但仍想避免复制,请通过 const 引用传递,例如const vector&lt;int&gt; &amp;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

【讨论】:

猜你喜欢
  • 2013-10-29
  • 2022-08-02
  • 2022-07-14
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 2021-10-22
相关资源
最近更新 更多