使用 size_type 作为迭代器偏移量 - GCC/Clang 和 MSVC 之间的区别

问题描述 投票:0回答:1

我正在尝试使用

size_type
作为
std::copy()
算法中字符串迭代器的偏移量。当
size_type
std::string::npos
时,GCC/Clang 不会抛出任何异常,但 MSCV 会抛出
cannot seek string iterator before begin

为什么MSCV会抛出这个异常?在这种情况下哪个编译器是正确的?

我已经在编译器资源管理器上使用以下编译器测试了该程序:

海湾合作委员会 -

x86-64 gcc 14.2

叮当-
x86-64 clang 19.1.0

MSCV -
x86 msvc v19.latest

这是一个最小的可重现程序

编译器资源管理器

#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstdint>
#include <string>

// timestamp in hhmmss.zzz format; can be in hhmmss format also
void test(const std::string& timestamp)
{
    std::string timeWithoutMs{};
    std::int32_t milliseconds{};

    auto itr = timestamp.find("."); 
    if( itr != std::string::npos)
    {
        milliseconds = std::stoi( timestamp.substr(itr + 1, timestamp.length() - itr));
    }

    std::copy( timestamp.begin(), timestamp.begin() + itr, std::back_inserter(timeWithoutMs));
    std::cout << timeWithoutMs << " - " << milliseconds << std::endl;
}

int main()
{
    test("135523.495");  
    test("135523");      // MSVC throws exception here
}
c++ c++11 exception compiler-specific
1个回答
0
投票

std::string::npos
的定义是
-1
。因此,当
itr
std::string::npos
时,
std::copy
调用如下所示:

std::copy( timestamp.begin(), timestamp.begin() + -1, std::back_inserter(timeWithoutMs));

请注意,在第二个参数中,您尝试递减字符串的开始迭代器。 MSVC 的标准库选择对此进行诊断,因为默认情况下它具有“检查迭代器”,这确保迭代器在范围内。 GCC 和 Clang 不需要对此进行诊断,因此它们的行为仍然正确,但您的程序无效,因为您尝试使用无效的迭代器范围调用

std::copy

您可以改用

std::string::substr
,当
count
参数为
std::string::npos
时,这是明确定义的:

timeWithoutMs = timestamp.substr(0, itr);

我还将

itr
变量重命名为
idx
,因为
std::string::find
返回索引而不是迭代器,我认为这会增加您的困惑。

© www.soinside.com 2019 - 2024. All rights reserved.