关于c ++:如何“删除”一个数组的一部分,并保持其余部分不通过它?

How to “delete” a part of an array and keep the rest without running through it?

我尝试在C++中实现一个算法。

在伪代码中,有:w←w[0..e],其中w是字符数组,e是整数。基本上我想保留数组的一部分并丢弃其余部分。

为了使程序正常工作,我使用了一个for循环,在该循环中,我扫描原始数组直到e,然后将值复制到一个新数组中。

1
2
3
char newArray[sizeIAlreadyKnow];
    for (int i=0;i<e;i++)
        newArray[i] = w[i];

我知道这是不有效的;有没有办法避免遍历原始数组?我也不太熟悉向量。他们有这个功能吗?

提前谢谢你


您可以使用std::string::resize。基本思想是使用std::string而不是char的原始数组。相应地,通过使用std::vector而不是T的原始数组,事情也变得更加简单和安全。


你说得对,你真的应该使用向量!

这里有很多文档,在C++和STD容器上也有很多很好的教程(问问谷歌的一些)

考虑到您的问题,矢量可以做什么(创建一个副本)

1
2
3
std::vector<char> myArray;
// fill your array, do watherver work you want with it
std::vector<char> newArray(&myArray[start], &myArray[end]);

或者在你的情况下(调整大小)

1
2
3
std::vector<char> myArray;
// fill your array, do watherver work you want with it
myArray.resize(e);

这里列出的向量上的每个方法都有示例。阅读这些可能会对您的算法的实现有很大帮助。

如果您需要的话,可以使用vector(或任何其他std容器)上的algorithm部分进行更多操作(如排序)。


用C++ BuiTin数组或STD::vector输出框是不可能的。

在D编程语言中,这是可能的。如果向下滚动到下面链接中标记为"介绍切片"的部分,您将找到一个关于如何实现的解释。简而言之,没有垃圾收集是不可能做到的。不能在C++中通过在指针中间调用一个数组来释放一个数组。因此,如果您试图从数组中切出中间部分,然后丢弃旧指针,您将无法释放内存,并且您的程序将泄漏。

http://dlang.org/d-array-article.html

现在,虽然使用语言结构是不可能的,但它在许多其他方面是可能的。

当然,还有一个明显的问题,如amxx所述:您可以简单地将您想要的数组片段复制到一个新的数组或向量中。但是,如果你关心性能,这不是最好的方法。矢量构造器amxx使用的仍然会循环所有元素并复制它们,即使你看不到。

对于更有效的解决方案,有C++迭代器。如果您有一个函数要处理数组的一个子集,那么您可以让您的函数接受迭代器,而不是数组或向量。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int sumElements(vector<int>::iterator first, vector<int>::iterator last)
{
    int sum = 0;

    for( ; first != last; ++first)
        sum += *first;

    return sum;
}

vector<int> numbers;

for(int i = 0; i < 100; ++i)
    numbers.push_back(i);

int sum = sumElements(numbers.begin() + 10, numbers.begin() + 20);

还有字符串视图:http://en.cppreference.com/w/cpp/experimental/basic_string_视图

字符串视图是对字符串切片的非拥有引用,但您可以将其视为其切片所在的对象,而不必处理一对迭代器。在内部,它只存储指向原始字符串的指针。不过,需要注意的是,由于字符串视图是一个不拥有的引用,原始字符串的生存期必须比指向它的任何字符串视图的生存期都长。

同样的事情也可以用一个向量来完成,但是标准库中还没有这方面的内容(甚至字符串视图仍然是实验性的)。

我想你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<class T>
class vector_view
{
    vector<T>::iterator first;
    vector<T>::iterator last;
public:
    vector_view(vector<T>::iterator first, vector<T>::iterator last)
        : first(first), last(last) { }

    const T& operator[](size_t i) const {
        assert(first + i < last);
        return *(first + i)
    }

    size_t size() const {
        return last - first;
    }
};

vector<int> numbers;
// ... init numbers with 100 numbers

vector_view<int> vv(numbers.begin() + 5, numbers.begin() + 32);

int number = vv[10];

我可能会坚持使用向量和迭代器来保持简单,但这里有它。

编辑:类似的想法,上面的讨论在这个建议的C++范围:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html