使用std::string::size_type而不是size_t有什么好处吗?

3

我正在审查另一位开发者的代码,其中包含以下内容:

std::string name;
...
std::string::size_type colon = name.find(":");

我认为使用 size_t 会更易理解,同样也很安全。因为 STL 标准规定 std::stringstd::basic_string<char, std::allocator>,而 std::allocator::size_typesize_t,所以这么做是可行的。
他想要保证 STL 标准不可能改变以使这个假设无效;如果标准可能发生变化,那么使用 size_type 比使用 size_t 更安全一些。
是否有可能发生这种情况?还有其他原因使用 size_type 而不是 size_t 吗?

1
size_type 适用于每个容器,无论它们使用什么类型,因此更加一致。 - chris
您可以假设 name 总是一个真实的 std::string - Chowlett
没有“STL标准”。C++标准可能会改变,但这时你就进入了另一种语言(称之为“C++11”),它不完全向后兼容你现在使用的语言(称之为“C++03”)。将代码从C++03移植到C++11需要知道哪些是破坏性变化,并加以考虑。所以如果你遇到这个问题,可以越过这座桥。在此之前,如果标准说它是正确的,那么就是正确的。在我看来,标准不太可能以一种打破使用默认分配器的stringvectorsize_t大小的代码的方式进行更改。 - Steve Jessop
1
你也可以猜测未来的标准可能会将find函数的返回类型更改为除了std::string::size_type之外的其他类型。对于这种破坏性变化,无法进行预测。 - Steve Jessop
@SteveJessop - 我认为你的第二点尤其相关。是的,string::size_type可能会改变,但是string::find()也可能改变。非常好的观点,谢谢! - Chowlett
2个回答

8

在模板化容器类型的代码中应该使用 size_type。当您的代码始终操作于 std::string 时,您可以直接使用 size_t


6

我认为最好的方法是使用auto,这样你就可以自动适应函数返回的任何内容:

auto colon = name.find(":");

它避免了您描述的问题,而且更加简短。

就像larsmans在评论中提到的那样,您可能想要在没有可用变量获取返回类型的情况下在struct或其他地方存储字符串索引。这也是可行的:

struct StoreStringIndex {
    decltype(declval<std::string>().length()) length;
};

但是它比std::string::size_type更加复杂,而且长度也不短。因此,如果要存储东西,您可能会想使用该类型的size_type,但对于本地变量和其他东西,请使用auto


不错的解决方案,但是你有些回避了问题;假设你想在structclass中存储字符串索引。 - Fred Foo
或者,decltype(declval<std::string>().find(":")) posn_of_colon;?我想知道在C++中是否错误地强制推断每种类型,除了在模板代码中无法避免的情况下。 - Steve Jessop
是的,它们(根据标准)确实如此,并且(根据标准)该类型是size_t,因此您可以使用它。它们都没有错,但由于您正在推断类型,我认为您希望从与其使用相关的表达式中推断出它,而不是从某个其他表达式中推断出具有相同类型的表达式。因此,如果成员用于存储长度,则从length()中推断,如果用于存储“索引或npos”则从find()中推断。 - Steve Jessop
好的,+1。我不知道declval - Fred Foo
@Chowlett 是的,但这与实际指定类型相同,而不是使用“auto”。您将无法看到任何区别,并且没有任何情况需要“auto”才能工作而不能使用“auto”。 - Seth Carnegie
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接