空deque vs矢量

时间:2015-03-01 14:45:58

标签: c++ stl

我在STL测验问题的样本中看到了以下内容

问:当您尝试编译并运行以下代码时会发生什么?

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <deque>

using namespace std;

void printer(int i) {
    cout << i << ", ";
}

int add (int a, int b) {
    return a+b;
}

int main() {

    vector<int> v1 = { 3, 9, 0, 2, 1, 4, 5 };
    set<int> s1(v1.begin(), v1.end());
    deque<int> d1;      // LINE I
    transform(s1.begin(), s1.end(), v1.begin(), d1.begin(), add);//LINE II
    for_each(d1.begin(), d1.end(), printer); //LINE III

    return 0;
}


A compilation error in LINE III
B program outputs: 3, 10, 2, 5, 5, 9, 14,
C program outputs: 3, 9, 0, 2, 1, 4, 5, 
D runtime error at LINE III 
E compilation error in LINE II 
F runtime error at LINE II 
G program outputs: 0, 1, 2, 3, 4, 5, 9, 

从阅读代码中我得到的答案是F,要么是因为 1复制到零大小的容器是未定义的行为 或者2 stl函数可能在运行时检查是否有足够的容量,如果没有抛出异常

我在gcc 4.8.1上编译并运行了代码

没有编译或运行时错误。 LINE III只是打印什么,因为我假设d1.begin()== d1.end()。 deque中没有有效的元素。

但是如果我添加LINE IV

for_each(d1.begin(), d1.begin()+7, printer); //LINE IV

打印

3, 10, 2, 5, 5, 9, 14, 

所以转换函数确实将7个元素写入“非托管”内存。

当我将LINE I更改为

vector<int> d1;

然后在LINE II上发生运行时错误。

问题

1可以说上述问题没有提供正确答案的选项。我不确定其他编译器会如何表现。

2我假设因为deques不一定使用连续存储,当转换函数向它写入元素时,通过deque迭代器发生某种形式的分配。但是,deque本身的大小仍为0.但是,向量迭代器在尝试写入内存时会导致崩溃。有没有人有详细的解释。

3当编写我自己的可以接受迭代器的实用程序函数时,在不知道任何有关底层容器的情况下,处理这种情况的最佳方法是什么,其中传递给无意中空容器的迭代器。我认为对于所有空容器,begin()== end()保证为true,所以最初执行此检查并抛出异常?

感谢

1 个答案:

答案 0 :(得分:1)

回答问题3:

你可以使用这样的东西来验证目标容器不仅不是空的,而且还有足够的大小:

if(std::distance(d1.begin(), d1.end()) < std::distance(s1.begin(), s1.end()))
{
    throw std::runtime_error("Not enough space");
}

您在问题1中的假设似乎是正确的。 gcc和clang都编译没有错误。

抱歉,我没有2的详细解释,但正如你所说,这是未定义的行为。当使用libstdc ++(clang和gcc)编译时,上面的示例运行良好deque,但是当使用libc ++和clang编译时,使用dequevector的段错误。因此,似乎libstdc ++中的deque的实现总是预先分配一些空间(即使在运行d1.shrink_to_fit()之后)。