代码之家  ›  专栏  ›  技术社区  ›  BoshWash

不同编译器中std容器的不同noexcept属性

  •  3
  • BoshWash  · 技术社区  · 7 年前

    是移动构造函数 noexcept 定义了容器实现的属性?我刚刚发现以下内容可以在clang中使用,但不能在gcc或msvc++中使用:

    std::vector<std::vector<std::unique_ptr<int>>> vector_a;
    std::vector<std::stack<std::unique_ptr<int>>> vector_b;
    vector_a.reserve(10);  // this works in all tested compilers
    vector_b.reserve(10);  // this only works in clang
    

    我的问题是,这是否是由于标准的不完整实施造成的,或者如果它只是没有定义(故意的?)。

    我测试了一些标准容器:

    #include <iostream>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <stack>
    
    int main() {
        std::cout << "Deque: " << std::is_nothrow_move_constructible<std::deque<float>>::value << std::endl;
        std::cout << "Vector: " << std::is_nothrow_move_constructible<std::vector<float>>::value << std::endl;
        std::cout << "Queue: " << std::is_nothrow_move_constructible<std::queue<float>>::value << std::endl;
        std::cout << "Stack: " << std::is_nothrow_move_constructible<std::stack<float>>::value << std::endl;
    }
    

    通用条款7.2.1:

    Deque: 0
    Vector: 1
    Queue: 0
    Stack: 0
    

    clang 5.0.0:

    Deque: 1
    Vector: 1
    Queue: 1
    Stack: 1
    

    适用于x64的Microsoft C/C++19.00.23506版本:

    德克:0
    矢量:1
    队列:0
    堆栈:0
    

    编辑

    使用向量作为基础容器的队列和堆栈的结果:

    std::cout << "Vector Stack: " << std::is_nothrow_move_constructible<std::stack<float, std::vector<float>>>::value << std::endl;
    std::cout << "Vector Queue: " << std::is_nothrow_move_constructible<std::queue<float, std::vector<float>>>::value << std::endl;
    

    通用条款7.2.1:

    Vector Stack: 1
    Vector Queue: 1
    

    clang 5.0.0:

    向量堆栈:1
    向量队列:1
    

    适用于x64的Microsoft C/C++19.00.23506版本:

    向量堆栈:1
    向量队列:1
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Nicol Bolas    7 年前

    stack queue 不是容器;它们是容器 适配器 . 他们 使用 作为模板参数提供给它们的容器类型。默认情况下,它们使用 std::deque .

    因此,他们转发他们正在适应的容器的无异常行为。所以如果 deque 在移动中投掷,a也会 堆栈 使用 德克 . 实际上,容器适配器 不要 转发其组件容器的noexcept行为。或者至少,标准没有要求他们这样做。

    至于实际集装箱的无异常状态, vector 需要具有 noexcept move(这是一个C++17更改;以前没有任何要求)。其余部分取决于实现。

        2
  •  2
  •   rustyx    7 年前

    只有 vector 的移动构造函数得到保证 noexcept 仅从C++17开始。

    deque , stack queue 移动构造函数不是 无例外 . LLVM的实现是 无例外 是一个很好的补充,不违反标准。

    您可能需要查看 deque::swap() ,它提供了类似的功能 无例外 (也是从C++17开始)。