【问题标题】:empty deque vs vector空双端队列与向量
【发布时间】:2015-05-01 22:08:27
【问题描述】:

我在一个 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()。双端队列中没有有效的元素。

但是,如果我添加 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 我假设因为双端队列不一定使用连续存储,所以当变换函数向其写入元素时,通过双端队列迭代器会发生某种形式的分配。然而,双端队列本身的大小仍然为 0。但是向量迭代器在尝试写入内存时会导致崩溃。谁有详细的解释。

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

谢谢

【问题讨论】:

  • 每个问题一个问题。
  • 反对的选民请发表评论
  • 你的假设 1 是正确的,因为程序有“未定义的行为”,任何给定的答案都是正确的。

标签: c++ stl


【解决方案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() 之后)。

【讨论】:

    猜你喜欢
    • 2012-09-07
    • 1970-01-01
    • 2013-05-21
    • 2018-05-18
    • 2017-05-06
    • 2020-10-29
    • 2018-07-02
    • 2014-03-30
    • 2013-03-14
    相关资源
    最近更新 更多