C ++风格与性能? [英] C++ style vs. performance?

查看:55
本文介绍了C ++风格与性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++风格与性能-正在使用C风格的东西,这快于某些C ++等效项,这是不好的做法吗?例如:

C++ style vs. performance - is using C-style things, that are faster the some C++ equivalents, that bad practice ? For example:

  • 请勿使用 atoi() itoa() atol()等!使用 std :: stringstream <-有时可能会更好,但总是吗?使用C函数有什么不好?是的,是C风格的,不是C ++,但是什么?这是C ++,我们一直在寻找性能..

  • Don't use atoi(), itoa(), atol(), etc. ! Use std::stringstream <- probably sometimes it's better, but always? What's so bad using the C functions? Yep, C-style, not C++, but whatever? This is C++, we're looking for performance all the time..

从不使用原始指针,而是使用智能指针-好的,它们非常有用,每个人都知道,我知道,我一直都在使用,而且我知道它们比原始指针要好多少,但有时使用原始指针是完全安全的.为什么不呢?不是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? "Not C++ style? <- is this enough?

不要使用按位运算-也是C风格的吗?什么当您确定自己在做什么时,为什么不呢?例如-不要按位交换变量( a ^ = b; b ^ = a; a ^ = b; )-使用标准的三步交换.不要使用左移乘以2.等等,等等.(好吧,这不是C ++风格还是C风格,但还是不好的做法")

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" )

最后,最昂贵的是-不要使用enum-s返回代码,它太C了,请对不同的错误使用异常"?为什么?好的,当我们谈论更深层次的错误处理时-好的,但是为什么总是这样呢?例如,这有什么问题?当我们谈论一个函数时,它返回不同的错误代码,而仅在该函数中执行错误处理时,该函数会调用第一个错误代码?我的意思是-无需在较高级别传递错误代码.例外情况相当缓慢,在特殊情况下是例外情况,而不是..美丽.

And finally, the most expensive - "Don't use enum-s to return codes, it's too C-style, use exceptions for different errors" ? Why? OK, when we're talking about error handling on deep levels - OK, but why always? What's so wrong with this, for example - when we're talking about a function, that returns different error codes and when the error handling will be implemented only in the function, that calls the first one? I mean - no need to pass the error codes on a upper level. Exceptions are rather slow and they're exceptions for exceptional situations, not for .. beauty.

等,等等,等等.

好的,我知道良好的编码风格非常非常重要<-代码应该易于阅读和理解.我知道微优化没有必要,因为现代编译器非常智能,并且编译器优化是很强大.但是我也知道异常处理的价格昂贵,smart_pointers的价格(多少)已实现,并且始终不需要smart_ptr..我知道,例如 atoi 并不像 std :: stringstream 那样安全",但是还是..性能如何?

Okay, I know that good coding style is very, very important <- the code should be easy to read and understand. I know that there's no need from micro optimizations, as the modern compilers are very smart and Compiler optimizations are very powerful. But I also know how expensive is the exceptions handling, how (some) smart_pointers are implemented, and that there's no need from smart_ptr all the time.. I know that, for example, atoi is not that "safe" as std::stringstream is, but still.. What about performance?

编辑:我不是在谈论一些非常困难的事情,这些事情仅是C风格的.我的意思是-不要奇怪使用函数指针或虚方法以及诸如此类的东西,即使从未使用过C ++程序员也可能不知道(而C程序员一直在这样做).我正在谈论一些更常见,更轻松的事情,例如在示例中.

EDIT: I'm not talking about some really hard things, that are only C-style specific. I mean - don't wonder to use function pointers or virtual methods and these kind of stuff, that a C++ programmer may not know, if never used such things (while C programmers do this all the time). I'm talking about some more common and easy things, such as in the examples.

推荐答案

通常,您所缺少的是C方式通常不会更快.它看起来更像是一种骇客,人们常常认为骇客的速度更快.

In general, the thing you're missing is that the C way often isn't faster. It just looks more like a hack, and people often think hacks are faster.

永远不要使用原始指针,而要使用智能指针-好的,它们真的很有用,每个人都知道,我知道,我一直都在使用,而且我知道它们比原始指针要好得多,但是有时使用原始指针是完全安全的.为什么不呢?

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 上使用原始指针的性能原理是什么?它们都没有任何开销,它们只是提供了更安全的语义.

Let's turn the question on its head. Sometimes it's safe to use raw pointers. Is that alone a reason to use them? Is there anything about raw pointers that is actually superior to smart pointers? It depends. Some smart pointer types are slower than raw pointers. Others aren't. What is the performance rationale for using a raw pointer over a std::unique_ptr or a boost::scoped_ptr? Neither of them have any overhead, they just provide safer semantics.

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

This isn't to say that you should never use raw pointers. Just that you shouldn't do it just because you think you need performance, or just because "it seems safe". Do it when you need to represent something that smart pointers can't. As a rule of thumb, use pointers to point to things, and smart pointers to take ownership of things. But it's a rule of thumb, not a universal rule. Use whichever fits the task at hand. But don't blindly assume that raw pointers will be faster. And when you use smart pointers, be sure you are familiar with them all. Too many people just use shared_ptr for everything, and that is just awful, both in terms of performance and the very vague shared ownership semantics you end up applying to everything.

不使用按位运算-也是C风格的吗?什么当您确定自己在做什么时,为什么不呢?例如-不要按位交换变量(a ^ = b; b ^ = a; a ^ = b;)-使用标准的三步交换.不要使用左移乘以2.等等,等等.(好吧,这不是C ++风格还是C风格,但还是不好的做法")

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" )

那是正确的.原因是更快".按位交换在许多方面都存在问题:

That one is correct. And the reason is "it's faster". Bitwise exchange is problematic in many ways:

  • 在现代CPU上速度较慢
  • 更容易出错,更容易出错
  • 它只能用于非常有限的一组类型

乘以2时,乘以2 .编译器知道此技巧,并会在更快的情况下应用.再有,换档有很多相同的问题.在这种情况下,它可能会更快(这就是编译器为您执行此操作的原因),但更容易出错,并且只能在一组有限的类型下使用.特别是,它可能会与您认为的类型一起很好地编译,因此可以安全地使用此技巧...然后在实践中将其炸掉.特别地,在负值上进行位偏移是一个雷区.让编译器为您导航.

And when multiplying by two, multiply by two. The compiler knows about this trick, and will apply it if it is faster. And once again, shifting has many of the same problems. It may, in this case, be faster (which is why the compiler will do it for you), but it is still easier to get wrong, and it works with a limited set of types. In paticular, it might compile fine with types that you think it is safe to do this trick with... And then blow up in practice. In particular, bit shifting on negative values is a minefield. Let the compiler navigate it for you.

顺便说一句,这与"C风格"无关.完全相同的建议也适用于C语言.在C语言中,常规交换比逐位hack快 still ,并且如果编译器完成了位移位而不是乘法操作,则 still 可以完成.这是有效的,并且速度更快.

Incidentally, this has nothing to do with "C style". The exact same advice applies in C. In C, a regular swap is still faster than the bitwise hack, and bitshifting instead of a multiply will still be done by the compiler if it is valid and if it is faster.

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

But as a programmer, you should use bitwise operations for one thing only: to do bitwise manipulation of integers. You've already got a multiplication operator, so use that when you want to multiply. And you've also got a std::swap function. Use that if you want to swap two values. One of the most important tricks when optimizing is, perhaps surprisingly, to write readable, meaningful code. That allows your compiler to understand the code and optimize it. std::swap can be specialized to do the most efficient exchange for the particular type it's used on. And the compiler knows several ways to implement multiplication, and will pick the fastest one depending on circumstance... If you tell it to. If you tell it to bit shift instead, you're just misleading it. Tell it to multiply, and it will give you the fastest multiply it has.

最后,这是最昂贵的-不要使用enum-s返回代码,它太C了,请对不同的错误使用异常"?

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

取决于您询问的人.我认识的大多数C ++程序员都为这两者找到了空间.但是请记住,关于返回码的不幸之处是它们很容易被忽略.如果那是不可接受的,那么在这种情况下,您也许应该选择例外.还有一点是,RAII与异常一起可以更好地工作,并且C ++程序员肯定尽可能使用RAII.不幸的是,由于构造函数无法返回错误代码,因此异常通常是指示错误的唯一方法.

Depends on who you ask. Most C++ programmers I know of find room for both. But keep in mind that one unfortunate thing about return codes is that they're easily ignored. If that is unacceptable, then perhaps you should prefer an exception in this case. Another point is that RAII works better together with exceptions, and a C++ programmer should definitely use RAII wherever possible. Unfortunately, because constructors can't return error codes, exceptions are often the only way to indicate errors.

但还是..性能如何?

but still.. What about performance?

那又如何呢?任何体面的C程序员都乐于告诉您不要过早优化.

What about it? Any decent C programmer would be happy to tell you not to optimize prematurely.

您的CPU每秒可能执行80亿条指令.如果您在第二秒内对 std :: stringstream 进行了两次调用,那么这是否会在预算中造成可衡量的损失?

Your CPU can execute perhaps 8 billion instructions per second. If you make two calls to a std::stringstream in that second, is that going to make a measurable dent in the budget?

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

You can't predict performance. You can't make up a coding guideline that will result in fast code. Even if you never throw a single exception, and never ever use stringstream, your code still won't automatically be fast. If you try to optimize while you write the code, then you're going to spend 90% of the effort optimizing the 90% of the code that is hardly ever executed. In order to get a measurable improvement, you need to focus on the 10% of the code that make up 95% of the execution time. Trying to make everything fast just results in a lot of wasted time with little to show for it, and a much uglier code base.

这篇关于C ++风格与性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆