14

标题有点用词不当,我的意思是“C with classes”。

让我解释一下,最近我买了一本书 ShaderX7,它附带了 Unigine 引擎的精简版(和旧版)副本,用于其中一篇关于阴影贴图技术的文章。

当我意识到,虽然作者使用 C++ 和继承以及所有 C++ 优点时,我正在涉足代码,但大多数(如果不是全部)方法内容本质上是 C 风格的代码;例如:

int Shader::get_param(const char *name,char *src,String &dest) const {
    char *s = src;
    int size = (int)strlen(name);
    while(*s) {
        if(!strncmp(s,name,size)) {
            if((s == src || strchr("\n\r",*(s - 1))) && strchr(" \t",*(s + size))) {
                src = s;
                s += size;
                dest.clear();
                while(*s && strchr(" \t",*s)) s++;
                while(*s && strchr(" \t\n\r",*s) == NULL) dest += *s++;
                if(dest.isEmpty()) {
                    Log::error("Shader::get_param(): can't get \"%s\" \n",name);
                    return 0;
                }
                memmove(src,s,strlen(s) + 1);
                return 1;
            }
        }
        s++;
    }
    return 0;
}

我并不是说这很糟糕,它完成了工作,这才是最重要的,但我更习惯于 C++ 风格的构造,包括 std::string、vectors 等......而且我大量使用了 Boost 库;所以这种风格让我有点意外。

使用这种代码真的比使用通用的 OO 方式更好/更快吗?

我是不是掉进了“太多抽象”的陷阱?

编辑:更正方法名称以明确它在做什么。

4

4 回答 4

26

首先,我必须承认我不是游戏开发者,尽管我过去开发了一个功能齐全的 3D 游戏引擎。

除此之外,我确实对优化、“破坏”语言等有几句话。

在开发应用程序(任何应用程序)时,优化的黄金法则是“在使其工作之前不要优化”。您需要完全支持应用程序中所需的所有功能,然后才应该优化它。原因各不相同;最重要的是,虽然您可能认为某事“缓慢”,但它可能不是您的瓶颈。您可能会花费大量时间来优化不需要优化的东西。此外,优化通常会模糊您的代码简单性和可维护性,这可能会导致近期或远期出现错误。如果这段代码不需要优化,那么您就白费了代码。

虽然这是优化的黄金法则,但有一个很大的例外。当您事先知道您的应用程序将承受最大压力时,您需要在开始时(在架构或设计阶段)以及沿途做出一些不同的选择。此外,平台越来越好、越来越快的一般规则并不适用于游戏,因为开发者之间的竞争处于技术的最前沿。这里有几点需要考虑:

  1. 某些语言功能可能代价高昂。C++ 中的异常就是一个很好的例子。
  2. 一些语言功能实际上可以节省您的代码,并且在运行时花费很少或不花费。C++ 模板就是一个很好的例子,尽管您仍然可能在编译期间创建大量代码,从而导致更大的二进制文件,因此可能会降低性能。
  3. 基础设施(例如 STL)是通用的。通过针对您的域制定解决方案,您可能会提高您的性能。一个简单的例子——如果你有一个总是 3 项长的向量,你肯定会比 stl::vector 实现更好。然而,这并非总是如此。如需进一步阅读,请参阅 Dov Bulka 的“Efficient C++”的第 11 章。对于您的问题,这是一本很好的书。

一般来说,将 C 与类一起使用是编写快速代码的良好开端,同时保留了结构化和精心设计的项目,但不应忽视 C++ 的全部优秀特性。通常情况下,尝试推出自己的解决方案来解决 C++ 涵盖的问题(例如,多态性)会比开箱即用的解决方案慢,除非您可以使解决方案非常针对手头的问题.

于 2010-08-31T04:59:18.340 回答
8

没有 STL 的 C++

正如我在职业生涯中看到的那样,游戏开发中最常使用的不是带有类的 C,而是没有 STL 的 C++。STL 的某些部分被认为对于合理的游戏引擎性能来说太慢了,尤其是流。其他部分提供了合理的一般性能,但处理内存分配的方式对于游戏来说大多是不可接受的——这在大多数情况下适用于字符串和向量库。可以在EASTL 白皮书中找到对此的出色广泛讨论。游戏开发人员经常使用 boost 甚至实现他们自己的替代方案来替代整个 STL 的一部分(请参阅Game STLEASTL)。

没有例外

有一个特殊的语言特性从未在任何性能关键的引擎部件中使用 - 异常处理。这是因为在最重要的游戏开发平台(Visual Studio x86/x64)上,异常是相当昂贵的,即使没有命中异常,你也要付出一些代价。在某些开发控制台平台甚至不提供它们的范围内避免异常,或者已知支持不完整、不可靠并且基本上“损坏”。

习惯了 C

除此之外,游戏程序员经常使用 C 而不是 C++,只是因为他们已经习惯了。

于 2010-08-31T05:10:16.630 回答
4

如果你真的想尽可能快地绘制图形,你首先要说

int size = (int)strlen(name);

这看起来像是在叫错树。

得到什么get_something?它似乎不是图形的。

优化不包括快速做错事。这是关于减少脂肪并将所有时间花在重要的事情上。如果您的图形引擎在字符串处理上浪费了大量周期,那么更改语言可能无法解决问题。

所以……尽可能方便、可维护和清晰地编写辅助函数。当您需要对关键路径进行微优化时,C++ 仍然涵盖了低级样式。

于 2010-08-31T04:59:08.897 回答
3

如果它:

  1. 工作,你对它很满意,不要碰它。
  2. 不行,改成你喜欢的样子,只要事后修好了。
  3. 工作,它不够快,让它更快(不是没有先分析)。

我猜你会陷入第一种情况,所以我建议不要管它。如果你需要改变一些东西,并且没有严重的性能问题,那么一定要在上面抛出一些 C++ 主义。在一般情况下,我发现很难阅读 C 风格的 C++ 程序员,他们要么:

  1. 没有时间或不关心学习 C++ 做事的方式(从安全角度来看,这确实是不可接受的),
  2. 正在挑选他们实际需要的 C++ 部分(非常明智),
  3. 或者他们真的需要 C 的性能特征(非常罕见)。

查看代码可能是这些情况中的任何一种。无论哪种方式,现在都无所谓,代码在您手中。

于 2010-08-31T04:56:04.663 回答