C++ 优化各种C/C+的代码+;编译程序

C++ 优化各种C/C+的代码+;编译程序,c++,compiler-construction,c-preprocessor,development-environment,compiler-optimization,C++,Compiler Construction,C Preprocessor,Development Environment,Compiler Optimization,对于那些为多个平台开发软件的人,您如何处理编译器可能比其他编译器做得更好的潜力 假设您是为OSX、Windows、Linux开发的,并且您使用的是Clang/LLVM、VS和GCC 因此,如果有人在OS X上编译你的应用程序,并且他们正在使用GCC,而另一个人在OS X上使用英特尔编译器进行编译,那么你可以为英特尔编译器优化代码部分(如果此人有) 你能检查一下预处理器指令吗 #ifdef __GCC_ // do it this way #endif #ifdef __INTEL__

对于那些为多个平台开发软件的人,您如何处理编译器可能比其他编译器做得更好的潜力

假设您是为OSX、Windows、Linux开发的,并且您使用的是Clang/LLVM、VS和GCC

因此,如果有人在OS X上编译你的应用程序,并且他们正在使用GCC,而另一个人在OS X上使用英特尔编译器进行编译,那么你可以为英特尔编译器优化代码部分(如果此人有)

你能检查一下预处理器指令吗

#ifdef __GCC_
    // do it this way
#endif

#ifdef __INTEL__
    // do it this way
#endif

#ifdef __GCC_WITH C++_V11_Support__
    // do it this way
#endif

#idfef __WINDOWS_VISUAL_STUDIO
    // do it this way
#endif
还是有更好的办法


如何找到编译器为检查编译器版本等提供的指令列表一般来说,编写编译器是为了优化公共代码,而不是专门为编译器编写的。所以一般来说,您应该专注于编写干净的代码,使用最快的算法。然而,有些编译器是可升级的,例如gcc,通过使用这些属性可以让编译器更好地完成其工作

例如,使用noreturn属性将允许gcc丢弃函数返回代码,从而最小化代码大小。我想很多编译器都有类似的暗示机制

我们可以这样做

#ifdef GCC
     #define NO_RETURN __attribute(...)
#else
     #define NO_RETURN
#endif

并且在代码中使用NO_RETURN。

一般来说,编写编译器是为了优化通用代码,而不是专门为编译器编写的。所以一般来说,您应该专注于编写干净的代码,使用最快的算法。然而,有些编译器是可升级的,例如gcc,通过使用这些属性可以让编译器更好地完成其工作

例如,使用noreturn属性将允许gcc丢弃函数返回代码,从而最小化代码大小。我想很多编译器都有类似的暗示机制

我们可以这样做

#ifdef GCC
     #define NO_RETURN __attribute(...)
#else
     #define NO_RETURN
#endif

并且在代码中使用NO_RETURN。

通常,优化遵循传统的80/20或90/10规则,“20%的代码需要80%的运行时间”(而“20%的代码需要80%的开发时间”)。如果你愿意,用80/20代替90/10——它几乎总是介于两者之间

因此,“针对特定编译器进行优化”的第一个阶段是找出代码的哪些部分比较慢,以及您是否可以通过一种适用于所有编译器的通用方式(例如,传递常量引用,而不是大型对象的副本)使其变得更好。一旦您对代码进行了所有通用的改进,您可能希望查看特定于编译器的优化,但这确实需要您获得足够的收益,以便在不同的编译器之间拥有不同的代码,这确实值得额外维护


一般来说,我会尽量避免“在不同的编译器中情况有所不同”

通常,优化遵循传统的80/20或90/10规则,“20%的代码需要80%的时间运行”(而“20%的代码需要80%的时间开发”)。如果你愿意,用80/20代替90/10——它几乎总是介于两者之间

因此,“针对特定编译器进行优化”的第一个阶段是找出代码的哪些部分比较慢,以及您是否可以通过一种适用于所有编译器的通用方式(例如,传递常量引用,而不是大型对象的副本)使其变得更好。一旦您对代码进行了所有通用的改进,您可能希望查看特定于编译器的优化,但这确实需要您获得足够的收益,以便在不同的编译器之间拥有不同的代码,这确实值得额外维护


一般来说,我会尽量避免“在不同的编译器中情况有所不同”

不要选择基于预定义宏的实现。让构建系统来控制它


这使您可以在单元测试期间构建多个实现并相互比较。

不要根据预定义的宏选择实现。让构建系统来控制它


这使您可以在单元测试期间构建和比较多个实现。

1)选择一种语言(C或C++)。2) 选择语言版本(C++03或C++11)。3) 用该语言为编写干净的代码。4) 信任编译器。在那之后,应该不会有太多需要人工干预的案例,这些案例可以进入一个方便的
arch
目录。我就是这样做的。但是我将各个实现分离到不同的文件中,并像上面一样通过预处理器选择要包含的文件。使用
#ifdef
作为特性而不是实现。如果可能的话,完全避免,正如@KerrekSB所建议的,让构建设置决定要选择的代码,而不是源文件。请参阅@KerrekSB-如果您可以通过说C++03到C++11来获得很多好处,该怎么办?例如,线程在C++03中以不同的方式使用。或者是Intel有一个特定的线程构建块。“这不是一个明智的例外吗?”杰森:你会得到的答案会因你和谁说话而大不相同。一个不做表演或跨平台工作的人会告诉你Kerrek刚刚告诉你的事情。您要寻找的答案实际上是Ben Voigt的答案——但更详细地说。1)选择一种语言(C或C++)。2) 选择语言版本(C++03或C++11)。3) 用该语言为编写干净的代码。4) 信任编译器。在那之后,应该不会有太多需要人工干预的案例,这些案例可以进入一个方便的
arch
目录。我就是这样做的。但是我将各个实现分离到不同的文件中,并像上面一样通过预处理器选择要包含的文件。使用
#ifdef
作为特性而不是实现。如果可能的话,完全避免,正如@KerrekSB所建议的,让构建设置决定要选择的代码,而不是源文件。见@KerrekSB-那怎么办