一般来说,您忽略的是 C 方式通常并不更快。它看起来更像是黑客攻击,人们经常think黑客攻击速度更快。
永远不要使用原始指针,而是使用智能指针 - 好吧,它们真的很有用,每个人都知道,我知道,我一直使用它们,我知道它们比原始指针好多少,但有时它是完全安全的使用原始指针..为什么不呢?
让我们把问题反过来看。有时使用原始指针是安全的。这就是使用它们的理由吗?关于原始指针实际上有什么吗?superior到智能指针?这取决于。Some智能指针类型比原始指针慢。其他人则不然。使用原始指针而不是指针的性能原理是什么?std::unique_ptr
or a boost::scoped_ptr
?它们都没有任何开销,它们只是提供更安全的语义。
这并不是说您永远不应该使用原始指针。只是你不应该仅仅因为你认为你需要性能,或者仅仅因为“它看起来安全”而这样做。当您需要表示智能指针无法表示的内容时,请执行此操作。根据经验,使用指针来指向事物,并使用智能指针来获取所有权东西的。但这是一个经验法则,而不是普遍规则。使用适合手头任务的任何一个。但不要盲目地认为原始指针会更快。当您使用智能指针时,请确保您熟悉它们。太多人只是用shared_ptr
对于所有事物,这都太糟糕了,无论是在性能方面还是在最终应用于所有事物的非常模糊的共享所有权语义方面。
不要使用按位运算 - 太 C 风格?啥?当你确定自己在做什么时为什么不呢?例如 - 不要按位交换变量 ( a ^= b; b ^= a; a ^= b; ) - 使用标准的三步交换。不要使用左移来乘以二。等等,等等(好吧,这不是 C++ 风格与 C 风格的对比,但仍然“不是很好的做法”)
那是正确的。原因是“它更快”。按位交换在很多方面都存在问题:
- 在现代 CPU 上速度较慢
- 它更微妙,更容易出错
- 它适用于非常有限的类型
当乘以二时,乘以二。编译器知道这个技巧,并且会应用它如果更快的话。再次,转变也存在许多相同的问题。在这种情况下,它可能会更快(这就是编译器会为您执行此操作的原因),但它仍然更容易出错,并且它适用于有限的类型集。特别是,它可能可以与您的类型一起编译良好think这样做是安全的……然后在实践中爆炸。特别是,负值上的位移位是一个雷区。让编译器为您导航。
顺便说一下,这与“C 风格”无关。完全相同的建议也适用于 C。在 C 中,定期交换是still比按位破解更快,并且位移而不是乘法将still如果它有效并且速度更快,则由编译器完成。
但作为一名程序员,您应该仅将按位运算用于一件事:对整数进行按位操作。你已经有了一个乘法运算符,所以使用that当你想繁殖的时候。而且你还有一个std::swap
功能。如果您想交换两个值,请使用它。也许令人惊讶的是,优化时最重要的技巧之一是编写可读的、有意义的代码。这使您的编译器能够理解代码并对其进行优化。std::swap
可以专门针对其所使用的特定类型进行最有效的交换。并且编译器知道几种实现乘法的方法,并且会根据情况选择最快的一种......如果你告诉它的话。如果你告诉它进行位移位,那么你只是在误导它。告诉它乘法,它会给你最快的乘法。
最后,最昂贵的 - “不要使用 enum-s 返回代码,它太 C 风格,对不同的错误使用异常”?
取决于你问的是谁。我认识的大多数 C++ 程序员都为这两者找到了空间。但请记住,返回码的一件不幸的事情是它们很容易被忽略。如果这是不可接受的,那么也许您应该在这种情况下选择例外。还有一点是,RAII 与异常一起工作效果更好,而且 C++ 程序员绝对应该尽可能使用 RAII。不幸的是,由于构造函数无法返回错误代码,因此异常通常是指示错误的唯一方法。
但仍然..性能怎么样?
那又怎样呢?任何正派的 C 程序员都会很乐意告诉您不要过早优化。
您的 CPU 每秒可能可以执行 80 亿条指令。如果您拨打两次电话std::stringstream
在那一刻,这会对预算产生明显的影响吗?
您无法预测性能。您无法制定能够产生快速代码的编码指南。即使你从不抛出任何异常,也从不使用stringstream
,你的代码仍然不会自动变快。如果您在编写代码时尝试进行优化,那么您将花费 90% 的精力来优化几乎从未执行过的 90% 的代码。为了获得可衡量的改进,您需要关注占执行时间 95% 的 10% 的代码。试图使一切快速只会导致浪费大量时间而几乎没有什么用处,并且代码库也变得更加丑陋。