关于 vector 的 operator[]

About operator[] of vector

我假设可以将 operator[] 用于任何 vector,而不管它包含的数据类型如何。我编写了这个算法来从字符串中删除空格,其中每个字符串都是使用 operator[].

从字符串向量中索引的
std::vector<string> substrs;
//after reading strings into the vector
//by means of user input
for(auto i : substrs){
    string s = substrs[i];
    s.erase(remove(s.begin(), s.end(), ' '), s.end());
}

由于以下错误,上述代码段无法编译:

error: no viable overloaded operator[] for type 'vector' (aka 'vector, allocator > >') string s = substrs[i];

谁能解释一下?

您正在使用错误的类型进行索引。您正在使用字符串进行索引。

for(auto i: substrs) {  ... }

auto 有一个 std::string 类型,不是算术类型。您不能按字符串索引向量。

如果需要索引,请尝试使用 for (size_t i = 0; i < substrs.size(); ++i) { ... },或者使用 C++ 的自动范围。

编辑 如代码学徒所述,您可能需要的是:

for (auto& str: substrs) { ... }

你根本不需要在这里建立索引。正如其他人所说,循环变量是向量的元素(std::string)。如果你使用auto&,那么你可以直接操作vector的成员:

std::vector<string> substrs;

for(auto& s : substrs){
    s.erase(remove(s.begin(), s.end(), ' '), s.end());
}

您的代码的问题是 "modern" for 循环遍历 std::vector 的值(它适用于任何集合)。它不会遍历向量元素的索引。

不过你得小心点。 for(auto s:substr) 将创建(并放入 s)每个字符串的副本。如果修改此副本,则不会修改集合中的实际字符串。您需要的是创建对向量中每个字符串的引用。看这个例子:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<std::string> a { "a", "b"};

    for (auto s: a) {
        s = "x";
    } 

    for (auto s: a) {
        std::cout << "element: " << s << std::endl;
    } 

    for (auto &s: a) {
        s = "x";
    } 

    for (auto s: a) {
        std::cout << "element: " << s << std::endl;
    } 

    return 0;
}

这将输出:

element: a
element: b
element: x
element: x

所以你需要解决的问题是:

for(auto &s: substrs){
   s.erase(remove(s.begin(), s.end(), ' '), s.end());
}

当使用基于范围的 for 时,控制变量采用您正在迭代的集合中项目的类型,而不是(如您所想的那样)集合中的数字索引.

事实上,根本不需要使用索引,因为基于范围的 for 让您可以 直接 访问集合中的每个项目 - 只需修改随心所欲。

下面的完整程序展示了如何做到这一点:

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

int main() {
    // Create a test vector.

    std::vector<std::string> stringVec;
    stringVec.push_back("Hello, my name is pax");
    stringVec.push_back("My hovercraft is full of eels");

    // Output the initial items (with spaces).

    for (const auto &str: stringVec)
        std::cout << '[' << str << ']' << std::endl;

    // Remove spaces from each item.

    for (auto &str: stringVec)
        str.erase(std::remove(str.begin(), str.end(), ' '), str.end());

    // Output the final items (no spaces any more).

    for (const auto &str: stringVec)
        std::cout << '[' << str << ']' << std::endl;
}

输出如预期的那样:

[Hello, my name is pax]
[My hovercraft is full of eels]
[Hello,mynameispax]
[Myhovercraftisfullofeels]