对于作用于整数向量的循环表现得很奇怪

时间:2016-05-01 02:25:28

标签: c++ for-loop vector

#include <iostream>
#include <vector>

std::vector<int> normalize(std::vector<int> a) {
    for (int j = a.size() - 1; j > 0; --j) {
        while (a[j] > 9) {
            a[j] = a[j] - 10;
            std::cout << '!'; //Just to test if the loop is executed (the correct # of times)
            ++a[j - 1];
        }
    }
// checks that the last digit isnt too large, makes new digit otherwise
    if (a[0] > 9) {
        a.insert(a.begin(), 0);
        while (a[1] > 9) {
            a[1] -= 10;
            ++a[0];
        }
    }

    return a;
}
// for debugging convenience
void printVector(std::vector<int> a) {
    for (int i = 0; i < a.size(); ++i) {
        std::cout << a[i] << ' ';
    }
    std::cout << std::endl;
}

int main()
{

    std::vector<int> a;
    a.push_back(1); a.push_back(2); a.push_back(33);
    normalize(a);
    printVector(a);

    return 0;
}

此程序将大整数表示为数字列表,例如,normalize函数将{1,2,33}更改为{1,5,3},表示为153。我是C ++的新手,所以我没有使用类,而且我没有使用任何大整数标题来实现这一点。

返回:!!! 1 2 33 好像矢量没有被改变。但那么“std :: cout'!'”行怎么会打印正确的次数,甚至while循环终止呢?

2 个答案:

答案 0 :(得分:3)

在你的功能中

std::vector<int> normalize(std::vector<int> a)

您按值传递a,因此一旦函数退出就不会被修改。为了使其工作,您应该使用当前的实现

auto result = normalize(a); // now we get the result
printVector(result); // and display it

为了避免制作不必要的副本,你应该通过const引用传递agument:

std::vector<int> normalize(std::vector<int> const& a)

如果您想修改传递给您的函数的参数,您应该通过引用传递:

std::vector<int> normalize(std::vector<int>& a) // now we can modify a

然而,将功能实现为没有副作用的黑盒子(如果可能的话)是一个好主意,因为它会使测试和多线程更容易,所以我建议通过const引用然后返回结果。

答案 1 :(得分:0)

您的函数使用pass-by-value。这意味着调用normalize(a);不会修改a,它会修改a的副本。

要解决此问题,有两种方法:

  1. 拨打电话a = normalize(a);
  2. 使函数具有void返回类型,并使用pass-by-reference(在参数名称之前的函数原型中放置&)。
  3. 第一种方式更自然,但遗憾的是对于大型载体存在性能问题,因此大多数人更喜欢第二种方式

    NB。在插入和调整之后,您目前无法处理a[0] > 9的可能性;并且首先存储最低有效数字会更简单,然后你可以附加而不是插入前面,你不需要将你的算法分成两部分。