【问题标题】:Is std::string::npos == -1 always true?std::string::npos == -1 总是正确的吗?
【发布时间】:2015-06-06 17:46:35
【问题描述】:

标题相对不言自明。我认识到与其他答案的相似之处,但所有这些都有不同的运算符安排(因此不同的铸造规则)。所以我需要一个能澄清这个特殊情况的答案。

如果有人能指出标准中解释这一点的部分,我很乐意投票并接受答案。

【问题讨论】:

    标签: c++ casting language-lawyer


    【解决方案1】:

    ,并非总是如此。然而,它比乍看起来要复杂一些:

    一开始,让我们看看std::string是什么(21.3/1):

    标题<string> 定义了basic_string 类模板,用于处理可变长度序列 类似 char 的对象和四个 typedef,stringu16stringu32stringwstring,它们命名了专业化 分别为basic_string<char>basic_string<char16_t>basic_string<char32_t>basic_string<wchar_t>

    从 21.4/5 开始:

    template<class charT, class traits = char_traits<charT>,
        class Allocator = allocator<charT> >
    class basic_string {
        typedef typename allocator_traits<Allocator>::size_type size_type;
        static const size_type npos = -1;
    // [other members omitted]
    };
    

    请注意,虽然npos 是用-1 初始化的,但它的类型取决于Allocator::size_type,这意味着在没有进一步了解的情况下,我们不能简单地假设string::npos == -1 甚至可以编译。

    现在string使用默认分配器(模板参数毕竟在标准库提供的typedef中有默认值),让我们检查一下20.6.9:

    typedef size_t size_type;
    

    现在,我们基本上可以将问题改写为:size_t(-1) == -1。现在发生的情况取决于子表达式的类型:左侧显然是 size_t 类型,而右侧是整数文字,其类型为 int,当这样编写时(没有进一步的限定符)。

    如果size_t 至少与int 一样大,则结果为true(对于标准狂热者:具有4.13 中定义的更大整数转换等级)。否则,左侧将被提升为int,导致类似0xFFFF == -1的比较(对于size_tuint16_tint具有32位),即@987654350 @。

    请注意,虽然 16 位系统本身不再很常见(除了一些非常小的外形尺寸的残余),int 并不受标准限制为 32 位。以 x86_64 为目标且具有 64size_t 和 128 位 int 的编译器在技术上是合规的。

    所有引用均来自 C++11 标准 (ISO/IEC 14882:2011)。

    【讨论】:

    • 作为后续问题,首先将左侧的类型转换为有符号类型会导致表达式得到保证吗?例如:(signed size_t) std::string::npos == -1
    • @randomusername 该转换会导致未定义的行为,因为npos 的值太大。只需执行以下操作:std::string::npos == std::string::size_type(-1) 就可以了。
    【解决方案2】:

    你从字面上问的问题有一个漏洞。

    如果int 具有(严格)大于string::size_type 的整数转换等级,并且int 可以存储string::size_type 的全部值范围,则string::npos == -1 将为假,因为这两个参数都将被提升为int,而不是被提升为string::size_type

    发生这种情况的环境非常不寻常。

    这来自通常的算术转换

    ...

    否则,如果具有无符号整数类型的操作数的秩大于或等于 其他操作数类型的等级,带符号整数类型的操作数应转换为 无符号整数类型的操作数的类型

    否则,如果带符号整数类型的操作数的类型可以表示所有的值 无符号整数类型的操作数的类型,无符号整数类型的操作数应 转换为带符号整数类型的操作数的类型。

    否则,两个操作数都应转换为对应的无符号整数类型 带符号整数类型的操作数的类型。

    【讨论】:

    • 那么你是不是建议string::size_type 在演员阵容中不会被符号扩展为int
    • @randomusername:string::size_type是无符号的,所以没有符号位可以扩展;转换会保留该值,因此它将转换为非负 int。注意npos是一个正值:实际上是string::size_type中可以存储的最大值。
    【解决方案3】:

    是的,定义为-1

    N4296 § 21.4 / 5 提供了 std::basic_string 的类模板,其中包括行

    static const size_type npos = -1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-28
      • 1970-01-01
      • 2018-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      相关资源
      最近更新 更多