【问题标题】:Was the Visual C++ STL human-generated or code-generated?Visual C++ STL 是人工生成的还是代码生成的?
【发布时间】:2011-11-01 16:57:59
【问题描述】:

每当我在调试代码时从 Visual Studio 的实现中打开任何与 STL 相关的代码时,我都会吓坏

// From <xtree>

if (_Where == begin())
    {   // insert at beginning if before first element
    if (_DEBUG_LT_PRED(this->comp,
        this->_Kfn(_Val), _Key(_Where._Mynode())))
        return (_Insert(true, _Where._Mynode(), _Val));
    }
else if (_Where == end())
    {   // insert at end if after last element
    if (_DEBUG_LT_PRED(this->comp,
        _Key(_Rmost()), this->_Kfn(_Val)))
        return (_Insert(false, _Rmost(), _Val));
    }
//...
else if (_DEBUG_LT_PRED(this->comp,
    _Key(_Where._Mynode()), this->_Kfn(_Val))
    && (++(_Next = _Where) == end()
        || _DEBUG_LT_PRED(this->comp,
            this->_Kfn(_Val), _Key(_Next._Mynode()))))
    {   // insert after _Where
    if (_Isnil(_Right(_Where._Mynode())))
        return (_Insert(false, _Where._Mynode(), _Val));
    else
        return (_Insert(true, _Next._Mynode(), _Val));
    }

cmets 的存在让我觉得它们好像是人写的,但糟糕的格式、在所有开头都随意使用下划线(为什么?)以及像 (++(_Next = _Where) == end() || _DEBUG_LT_PRED ...) 这样极其难以理解的条件让我觉得它们是从另一段源代码生成的,不是按原样编写的。

有谁知道是哪种情况? (如果它是从其他代码生成的,我很想知道如何/为什么这样做。)


为了记录,这里是同一件事,但“格式正确”:

if (Where == begin())
{
    // insert at beginning if before first element
    if (DEBUG_LT_PRED(this->comp, this->Kfn(Val), Key(Where.Mynode())))
        return (Insert(true, Where.Mynode(), Val));
}
else if (Where == end())
{
    // insert at end if after last element
    if (DEBUG_LT_PRED(this->comp, Key(Rmost()), this->Kfn(Val)))
        return (Insert(false, Rmost(), Val));
}
//...
else if (DEBUG_LT_PRED(this->comp, Key(Where.Mynode()), this->_Kfn(Val))
    && (++(Next = Where) == end()
        || DEBUG_LT_PRED(this->comp, this->_Kfn(Val), Key(Next.Mynode()))))
{
    // insert after Where
    if (Isnil(Right(Where.Mynode())))
        return (Insert(false, Where.Mynode(), Val));
    else
        return (Insert(true, Next.Mynode(), Val));
}

恕我直言这个更像是人类写出来的结果,但话又说回来,我不知道。

【问题讨论】:

  • 我怀疑这些条件是在几年的发展中逐步“成长”的。仅被非常熟悉库内部结构和那里使用的习语的人认为是可读的,目的是编写不超过绝对必要的代码行。可能 STL 设计者的目标与“应用程序”程序员的目标大不相同。
  • 所有代码都是人为生成的,因为至少有人给出了关于输出什么以及应该如何格式化的指令。

标签: c++ visual-studio visual-c++ stl


【解决方案1】:

两件事:

  1. 缩进实际上很好,虽然现在不寻常(我个人讨厌它):他们使用四个缩进,这是通过空格实现的,但对所有 8 的倍数使用制表符。这曾经是几乎所有地方的标准(值得注意的是,它仍然是 Vim 等几个编辑器的默认设置)。但因此,只有将标签宽度设置为 8 时,代码才会正确缩进。所以代码 实际上 看起来像这样:

    else if (_Where == end())
        {   // insert at end if after last element
            if (_DEBUG_LT_PRED(this->comp,
                _Key(_Rmost()), this->_Kfn(_Val)))
                return (_Insert(false, _Rmost(), _Val));
        }
    

    虽然仍然不寻常,但完全合乎逻辑且清晰易读。

  2. 标准库仅使用保留标识符以避免名称与客户的 C++ 代码冲突,这是一种很好的风格(甚至是强制要求?)。这些保留名称要么是以下划线开头的名称,后跟一个大写字母(_DEBUG_LT_PRED_Key),要么是两个下划线(不在此代码中,但 GCC libstdc++ 中到处都是 __x 等)。

因此是字母汤。

但是,是的,这段代码确实是手动编写的——至少在 GCC 的情况下是这样。 libstdc++ 的活动源代码分支看起来与上面的代码完全一样,并且不是自动生成的。

【讨论】:

  • +1 非常 关于第 1 点的有趣注释,但是 (2) 为什么标识符会与任何东西冲突? C++中没有范围规则吗? (3) 这仍然不能解释为什么 if 条件如此丑陋/不可读 :\ ,以及 (4) 这与 GCC 有什么关系?
  • @Mehrdad C++ 中的范围规则很烂,因为 C++ 有宏。那些可以摧毁一切。关于(4):嗯,所有的标准库实现看起来有点像这样,出于同样的两个原因。我不确定你对if 条件的问题是什么——除了它们包含调试代码这使得它们更难理解......
  • @Konrad:关于ifs:这对你来说是不是有点难以理解,有扩展的条件和副作用等等? ... else if (_DEBUG_LT_PRED(this->comp, _Key(_Where._Mynode()), this->_Kfn(_Val)) && (++(_Next = _Where) == end() || _DEBUG_LT_PRED(this->comp, this->_Kfn(_Val), _Key(_Next._Mynode()))))...
  • @Mehrdad:难以阅读,是的......我猜(希望?)他们测量它提供了更好的生成程序集。
  • @Mehrdad 我不这么认为。请记住,通过适当的选项卡宽度设置,它看起来像这样:gist.github.com/1164541 - 非常符合逻辑缩进。诚然,如果可以预防的话,我个人不会在条件句中使用副作用。但是你的“正确格式化”的代码也仍然有这些。
【解决方案2】:

VC++ 提供的 STL 是由Dinkumware 编写的(并且可能经过改编)。

据我所知,它是由人类编写的,但经过大量优化,可能会在维护者口中留下酸味。毕竟,我们建议初学者不要对他们的代码进行微优化是有原因的——这会让人难以阅读。但是,我们确实希望像 STL 这样重要的库能够进行大量优化:无论如何我们都不必维护它。

我自己觉得它很可读:

  • 缩进良好(无法正确显示 GCC 的 STL)
  • 已评论
  • 没有杂乱的预处理器指令(ala Boost,但显然只满足一个编译器更容易)

您可能希望查看 libc++ 以说服自己,即使是人工编写的库,没有遗留代码(它是新鲜的),也会变得相当复杂。示例&lt;algorithm&gt;(喜欢排序算法)。

【讨论】:

  • +1... 也许只有我一个人,但我发现您链接的&lt;algorithm&gt; 比我的&lt;xtree&gt; 更具可读性。你需要做的就是去掉前面的下划线,它就变成了正常的。
  • GCC 的 stdlibc++ 使用相同的缩进约定(尽管使用两个空格而不是 4 个)。您链接到的是 LLVM 的实现,GCC’s looks veery different
  • @Konrad:啊,谢谢,因此这是我的编辑器的设置问题!这是一个奇怪的约定......真的:/
  • @Matthieu - 据我所知,Dinkumware 有一个配置系统,可以从更大的代码库中选择系统特定的代码。这隐藏了他们的配置“宏”。
  • @Bo:我认为 Boost 也存在同样的情况,即有一个实用程序可以根据您的编译器剥离代码中未使用的部分,不过我从未使用过它。
【解决方案3】:

MS STL 的原始公司是Dinkumware。他们有这种糟糕的代码风格,即使 MS 不再使用它们,它看起来仍然存在。我敢肯定它是手写的,可能都是同一个人写的,我可以说出他的名字,但我想我不会。

【讨论】:

  • 尽管他在 VCBlog 中确实有一个关于 STL 及其工作原理的非常有趣的系列。至少,当你发现他的名字时,你将不得不轻笑。
  • @RedX - 姓名首字母合适的人是 MS 维护者,而不是原作者。
  • 这样写代码并不丢人。 STL 的目标是优化,而不是在易于阅读比速度和大小更重要的应用程序级别。
  • 从 cmets 判断,我假设他们在谈论“STL”,Steven T Lavavej,根据他的网站,他是一个非常酷的人。自从 STL 存在之前,他就以“STL”消失了。
猜你喜欢
  • 2010-09-20
  • 2020-11-11
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2011-03-13
  • 2012-05-11
相关资源
最近更新 更多