gpt4 book ai didi

C++ 风格与性能?

转载 作者:IT老高 更新时间:2023-10-28 12:49:19 26 4
gpt4 key购买 nike

C++ 风格与性能 - 使用 C 风格的东西,比某些 C++ 等价物更快,这种不好的做法?例如:

  • 不要使用 atoi() , itoa() , atol() , 等等。 !使用 std::stringstream <- 可能有时会更好,但总是这样?使用 C 函数有什么不好?是的,C 风格,而不是 C++,但无论如何?这是 C++,我们一直在寻找性能。
  • 永远不要使用原始指针,而是使用智能指针 - 好吧,它们真的很有用,每个人都知道,我知道,我一直在使用,而且我知道它们比原始指针好得多,但有时它是完全安全的使用原始指针.. 为什么不呢? “不是 C++ 风格?<- 够了吗?
  • 不要使用按位运算 - 太 C 风格?什么?为什么不,当你确定你在做什么时?例如 - 不要按位交换变量( a ^= b; b ^= a; a ^= b; ) - 使用标准的 3 步交换。不要使用左移来乘以二。等等等等。(好吧,这不是 C++ 风格与 C 风格,但仍然“不是好的做法”)
  • 最后,最昂贵的 - “不要使用 enum-s 来返回代码,它太 C 风格了,对不同的错误使用异常”?为什么?好的,当我们谈论深层次的错误处理时 - 好的,但为什么总是这样?这有什么问题,例如 - 当我们谈论一个函数时,它返回不同的错误代码,而当错误处理将只在调用第一个的函数中实现时?我的意思是 - 无需在上层传递错误代码。异常相当慢,它们是 异常(exception) 用于特殊情况,而不是用于 .. 美。
  • 等等等等等等

  • 好的,我知道好的编码风格是 非常非常重要 <- 代码应该易于阅读和理解。我知道不需要微优化,因为现代编译器非常聪明,而且 Compiler optimizations非常强大。但我也知道 exceptions handling 有多贵,如何实现(一些)smart_pointers,并且一直不需要 smart_ptr.. 我知道,例如, atoi不像 std::stringstream 那样“安全”是,但仍然......性能如何?

    编辑 :我不是在谈论一些非常困难的事情,那只是 C 风格特定的。我的意思是 - 不要怀疑使用函数指针或虚拟方法以及这些东西,如果从未使用过这些东西,C++ 程序员可能不知道(而 C 程序员一直这样做)。我说的是一些更常见和容易的事情,比如在例子中。

    最佳答案

    通常,您缺少的是 C 方式通常并不快。它看起来更像是一个黑客,人们通常认为黑客更快。

    Never use raw pointers, use smart pointers instead - OK, they're really useful, everyone knows that, I know that, I use the all the time and I know how much better they're that raw pointers, but sometimes it's completely safe to use raw pointers.. Why not?



    让我们把问题转过来。有时使用原始指针是安全的。仅此一项是使用它们的理由吗?是否有任何关于原始指针实际上优于智能指针的内容?这取决于。一些智能指针类型比原始指针慢。其他人不是。在 std::unique_ptr 上使用原始指针的性能原理是什么?或 boost::scoped_ptr ?它们都没有任何开销,它们只是提供更安全的语义。

    这并不是说你永远不应该使用原始指针。只是你不应该仅仅因为你认为你需要性能,或者仅仅因为“它看起来很安全”而这样做。当您需要表示智能指针无法表示的内容时,请执行此操作。根据经验,使用指针指向事物,使用智能指针来获取事物的所有权。但这是一个经验法则,而不是通用规则。使用适合手头任务的任何一种。但是不要盲目地认为原始指针会更快。当您使用智能指针时,请确保您熟悉它们。太多人只用 shared_ptr对于一切,这太糟糕了,无论是在性能方面还是在最终应用于一切的非常模糊的共享所有权语义方面。

    Don't use bitwise operations - too C-style? WTH? Why not, when you're sure what you're doing? For example - don't do bitwise exchange of variables ( a ^= b; b ^= a; a ^= b; ) - use standard 3-step exchange. Don't use left-shift for multiplying by two. Etc, etc.. (OK, that's not C++ style vs. C-style, but still "not good practice" )



    那个是对的。原因是“它更快”。按位交换在很多方面都存在问题:
  • 在现代 CPU 上速度较慢
  • 更微妙更容易出错
  • 它适用于非常有限的一组类型

  • 当乘以二时,乘以二。编译器知道这个技巧,如果它更快,就会应用它。再一次,换挡也有许多相同的问题。在这种情况下,它可能会更快(这就是编译器会为您做的原因),但仍然更容易出错,并且它适用于有限的类型集。特别是,它可能可以很好地编译您认为可以安全地使用此技巧的类型......然后在实践中爆炸。特别是,负值的位移是一个雷区。让编译器为您导航。

    顺便说一句,这与“C 风格”无关。完全相同的建议适用于 C。在 C 中,常规交换仍然比按位 hack 快,如果有效且速度更快,编译器仍将执行位移而不是乘法。

    但是作为程序员,您应该只将按位运算用于一件事:对整数进行按位操作。你已经有了一个乘法运算符,所以当你想乘法时使用它。你还有一个 std::swap功能。如果要交换两个值,请使用它。优化时最重要的技巧之一,也许令人惊讶的是,编写可读的、有意义的代码。这使您的编译器能够理解代码并对其进行优化。 std::swap可以专门为使用它的特定类型进行最有效的交换。并且编译器知道几种实现乘法的方法,并且会根据情况选择最快的一种......如果你告诉它。如果你告诉它移位,你只是在误导它。告诉它乘法,它会给你最快的乘法。

    And finally, the most expensive - "Don't use enum-s to return codes, it's too C-style, use exceptions for different errors" ?



    取决于你问谁。我认识的大多数 C++ 程序员都为两者找到了空间。但请记住,返回码的一个不幸之处是它们很容易被忽略。如果这是 Not Acceptable ,那么在这种情况下,也许您应该更喜欢异常(exception)。另一点是 RAII 与异常一起使用效果更好,并且 C++ 程序员绝对应该尽可能使用 RAII。不幸的是,由于构造函数不能返回错误代码,异常通常是指示错误的唯一方法。

    but still.. What about performance?



    怎么样?任何体面的 C 程序员都会乐于告诉您不要过早地优化。

    您的 CPU 每秒可以执行大约 80 亿条指令。如果您两次拨打 std::stringstream在那一刻,这是否会对预算产生可衡量的影响?

    你无法预测性能。你不能制定一个能产生快速代码的编码指南。即使你从不抛出一个异常,也从不使用 stringstream ,您的代码仍然不会自动变快。如果您在编写代码时尝试优化,那么您将花费 90% 的精力来优化几乎从未执行过的 90% 的代码。为了获得可衡量的改进,您需要关注占执行时间 95% 的 10% 的代码。试图让一切变得快速只会导致浪费大量时间而几乎没有显示出来,并且代码库更加丑陋。

    关于C++ 风格与性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4171858/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com