C字符串的长度:std::strlen() vs. std::char_traits<char>::length()

4

这两种方式都是等效的,它们返回以空字符结尾的字符序列的长度。有没有更倾向于其中一种的原因呢?


第二个版本使用标准C++头文件<string>,而第一个版本使用C头文件<cstring> - David G
1
我总是更喜欢避免使用(当然也很好的)C函数,如果有C++的替代方法的话。 - masoud
@MM。(当然,前提是您正在使用C++编程。) - user529758
5个回答

6
使用更简单的替代方案。虽然std::char_traits::length很好,但对于C字符串它做的是相同的事情,而且代码更长。
避免代码膨胀对自己有好处。我非常喜欢C++函数,而不是C等价物(例如,我永远不会使用std::strcpystd::memcpy,因为有一个完全可以用的std::copy)。但是避免使用std::strlen就有点傻了。
只使用C++函数的一个原因是接口一致性:例如,std::strcpystd::memcpy都有糟糕的接口。然而,std::strlen是一个在C++最佳传统中完全可以的算法。它不能泛化,确实如此,但标准库中其他类特定的自由函数也是如此。

嗯,不完全是傻的(如果您不能确保字符串中有空终止符),但您可以使用strnlen来解决这个问题。如果您必须支持不同大小的字节集(例如,一个用于UNICODE的构建和一个用于非UNICODE的构建),则char_traits版本更有用。 - Zac Howland
1
@Zac 嗯,(显然)我是在谈论上述替代方案之间的直接比较。 - Konrad Rudolph
点击添加太快了...我还没想好,你已经回复了 :) - Zac Howland

3

std::strlen()是C标准库中的一个遗留函数,只能操作const char*类型的字符串(如果该字符串没有以空字符结尾,则其行为是未定义的,因此并不安全)。 如果字符串使用宽字符集(例如const unsigned short*),则std::strlen()无法正确操作。

std::char_traits<T>::length()操作的是T类型的值(例如,如果是unsigned short,则仍将正常工作,但也需要一个以空字符结尾的值 - 即最后一个值必须是T(0) - 如果传递给它的T数组没有以空字符结尾,其行为也是未定义的)。

一般来说,在处理字符串时,最好使用std::string::length()而不是使用C风格的字符字符串。


5
如果将一个非空结束字符序列传递给 char_traits::length(),也会产生未定义行为。 - Ruup
@Ruup 确实。我没有写上它,因为我认为它是不言自明的,但为了完整起见,我会加上它。 - Zac Howland

0

Zack Howland和Konrad Rudolph都有一定的观点。谢谢。我接受两个答案。总结回复如下: 似乎没有任何除了个人偏好之外的选择,无论是更短的代码还是C++标准库(由于这不是问题的重点,因此我忽略了概括性)。


0
自 C++17 开始,std::char_traits<char>::length()constexpr,这意味着如果可能的话(即如果参数是常量),应该在编译时计算字符串长度。
实际上,现代编译器已经将 strlen 优化为对于 constexpr 表达式在编译时计算字符串长度,尽管这不是真正的标准。
话虽如此,我同意 strlen 更易读。

-2

std::strlen() 是一个兼容 C 标准库的函数(即使它是 ISO C++ 的一部分),它以 const char* 作为参数。length()std::string 类族的一个方法。因此,如果你想在 std::string 上使用 strlen(),你需要写成:

strlen(mystring.c_str())

这比mystr.length()不太整洁。除此之外,在char类型中应该没有明显的区别。


2
std::char_traits<T>::length(const T* t) 不是 std::string 的一部分,而是 std::char_traits 的一部分。 - Zac Howland
这就是我所说的“家族”类,包括std::string。 - Alexander L. Belikoff
那个措辞可能不是你想要表达的。std::string使用std::char_traits(像iostreams等其他STD类一样),但是std::char_traitsstd::string一无所知。实际上,std::string::length甚至不会查找空终止符(它返回size成员的值)。std::char_traits<T>::length()确实会查找空终止符。 - Zac Howland
2
不,你误解了OP的意思。除此之外,std::strlenstd::basic_string::length之间确实存在着明显的区别。前者假定字符串以空字符结尾,而后者允许字符串内部存在空字符。 - Konrad Rudolph
你应该始终谨慎使用 strlen 而不是 string::c_str(),因为后者有时会由于字符串中的 \0 导致报告错误的长度。 - masoud
谢谢。我不知道那个。 - Alexander L. Belikoff

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