cplusplus.com给出了哪些错误、误解或糟糕的建议

What are the errors, misconceptions or bad pieces of advice given by cplusplus.com?

本文关键字:误解 错误 com cplusplus      更新时间:2023-10-16

有一些对C++标准库的引用,包括宝贵的ISO标准、MSDN、IBM、cppreference和cplusplus。就我个人而言,在编写C++时,我需要一个具有快速随机访问、短加载时间和使用示例的参考,我发现cplusplus.com非常有用。然而,我经常在SO上听到关于该网站的负面意见,所以我想具体说明一下:

cplusplus.com给出了哪些错误、误解或糟糕的建议?使用它进行编码决策的风险是什么?

我希望能够用标准的准确引用来回答SO上的问题,因此我想立即发布可用的链接,如果不是因为这个问题,cplusplus.com将是我的选择网站。

编辑:自编写此答案以来,std::remove的文档已经修复。list::remove也是如此。

让我给你举一个例子,向你展示cpluscplus.com是如何出错的。

<algorithm>考虑std::remove函数。

事实是std::remove并没有从容器中移除该项。这是因为std::remove只使用一对迭代器,对实际包含项的容器一无所知。事实上,std::remove不可能知道底层容器,因为它无法从一对迭代器中发现迭代器所属的容器。因此std::remove并没有真正删除这些项,只是因为它不能实际从容器中移除项的唯一方法是调用该容器上的成员函数。

因此,如果你想删除项目,那么使用擦除删除习语:

 v.erase(std::remove(v.begin(), v.end(), 10), v.end()); 

但是cplusplus.com给出了关于std::remove的不正确的信息。上面写着

请注意,此函数不会更改经过新端的元素,这些元素保持其旧值,并且仍然可以访问

这是不对的。范围[new_end, old_end)中的迭代器仍然是不可引用的,但这并不意味着它们保留了旧值并且仍然可以访问它们未指明。


类似地,cplusplus.com也给出了关于list::remove不正确的信息。上面写着,

请注意,存在一个全局算法函数remove,它具有类似的行为,但在两个迭代器之间运行。

这是完全错误的。全局移除(即std::remove)与list::remove不相似,因为我们看到前者并没有真正从容器中移除项,因为它不能,而后者(成员函数)确实移除了项目,因为它可以。

这个答案复制自我在以下主题中的另一个答案,几乎没有修改:

  • STL删除不';没有按预期工作吗

注意:由于我最近在回复上述主题时遇到了这个问题,我记得了。过去两年我遇到了很多错误,但我不记得了。如果我再遇到的话,我以后可能会补充一些。

我将提出一个稍微相反的意见。cplusplus.com上有很多好的信息。对它吹毛求疵,是的,它当然有问题,但哪个网站没有?当然不是这个网站。住在玻璃房子里的人不应该扔石头。这里也有很多错误信息。有些公认的答案是完全错误的,有些被否决的答案(有些是否定的!)是正确的。

cplusplus.com的一个问题是它是一个封闭的网站;提到的大多数其他参考网站也是如此。这与社区开发的网站(如Stack Overflow)背道而驰。获得进行可信编辑的能力并不需要那么长时间,即使是最新的新手也可以很容易地提出改进建议。与cplusplus.com相比,如果你不是他们的员工,你就是一个永远的新手。即使你是WG21的关键成员,如果你在该网站的某个地方看到错误,你也必须通过他们的电子邮件报告机制。可憎的事物

一个解决方案是我们在这个网站上开发自己的C++参考。这将需要相当多的工作。我们必须小心,不要太迂腐/太技术化;很明显,cplusplus.com至少雇佣了一些技术编辑来阻止学究。我们必须把信息组织得井井有条;这里的常见问题解答组织得不好。我们还必须非常小心,不要直接从标准中说太多;这是违法的。

http://www.cplusplus.com/reference/clibrary/cstring/strncpy/

没有提到"如果复制发生在重叠的对象之间,则行为是未定义的。"(C89标准中的4.11.2.4。我手头没有C90的副本,这正是C++03实际指的,但它们应该只在页码等方面有所不同。)

cplusplus.com提供的文档通常不正确或不完整

一旦有了这样的例子,cplusplus.com.上的atoi文档

atoi
在Return部分,如果在使用函数时无法进行转换,则不会提及返回值为0。

cplusplus.com返回部分声明"…如果转换后的值超出了int可表示值的范围,则会导致未定义的行为。"

这是正确的,根据标准"如果字符串的数值不能用int表示,那么行为是未定义的"。

然而,该部分并不完整,因为它没有提到0作为返回值,这可能会产生误导。"…不执行转换,返回零。"这句话以前在描述段中出现过,但必须在Return部分中出现。

cplusplus.com上提供的许多示例源代码都不正确
许多新手在查阅这些参考资料时都会犯民谣错误。

举个例子:

编辑:我之前引用的例子是错误的。

type_info的文档试图首先解释typeid,但失败了:

typeid可以直接应用于类型,在这种情况下,它返回信息或对象,其中如果它返回有关对象的类型。

当typeid应用于指向多态类类型声明或继承虚拟函数),它考虑其动态类型(即最派生对象)。

现在第二段已经与第一段不一致了。在typeid(*ptr)中,typeid被应用于表达式。这是非常重要的,因为staticdynamic类型的概念只在表达式的上下文中有意义,而在对象的上下文中没有意义。它还漏掉了typeid(foo())这样的情况。

此外,第二段省略了参考文献。它们也可以具有不同于它们引用的对象的动态类型的静态类型。

std::pair<T1,T2>::operator==的文档表明,两个元素都经过了相等性测试。std::pair<T1,T2>::operator<的文献表明,只有当第一个元素相等时,才考虑第二个元素。

"相等"一词出现在这两种情况下。然而,只有在第一种情况下,它才真正意味着T::operator==。在第二种情况下,相等意味着!(a.first<b.first || b.first<a.first)