【问题标题】:Compile time validation for iterator usage?迭代器使用的编译时间验证?
【发布时间】:2023-03-25 09:28:01
【问题描述】:

我有以下粗心的 C++ 代码,它在 VC10 下可以顺利编译,但在运行时却惨遭失败。我想知道是否有办法在编译时验证这种错误?

#include "stdafx.h"
#include <set>

void minus(std::set<int>& lhs, const std::set<int>& rhs)
{
    for ( auto i = rhs.cbegin(); i != rhs.cend(); ++i )
    {
        lhs.erase(i); // !!! while I meant "*i" !!!
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int v_lhs[] = {0,1,2,3,4,5};
    std::set<int> s_lhs(&v_lhs[0], &v_lhs[sizeof(v_lhs) / sizeof(int)]);

    int v_rhs[] = {1,3,5};
    std::set<int> s_rhs(&v_rhs[0], &v_rhs[sizeof(v_rhs) / sizeof(int)]);

    minus(s_lhs, s_rhs);
    return 0;
}

请注意,我完全意识到 C++11(VC10 早期部分采用)已经纠正了“擦除”实际上采用“const_iterator”的行为。

在此先感谢您提供宝贵意见。

【问题讨论】:

    标签: c++ visual-studio-2010 c++11 iterator erase


    【解决方案1】:

    C++ 不是一种读心语言。它所知道的只是类型。它知道erase 需要一个迭代器。它知道i 是一个相同类型的迭代器。因此,就C++的编译器规则而言,调用erase(i)是合法的。

    编译器无法知道您想要做什么。编译器也没有办法知道i内容 不适用于erase 的这种特殊用途。你最好的选择是尽量避免错误。基于范围的for(或使用std::for_each)会在这里为您提供帮助,因为它们都隐藏了迭代器。

    【讨论】:

    • 对,在这种特定情况下,我最好的选择似乎是要小心,并且可能依赖于某种级别的运行时检查,例如,在调试期间打开检查的迭代器,但这又依赖于发货前的代码覆盖率测试。或者在开发过程中发现的代码总是容易出现错误!您关于通过利用 for_each 或基于范围的 for 避免迭代器的观点对于一般容器内容操作确实有其优点(在其他一些特殊用例中,在迭代时修改容器是典型的例外)。
    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多