std :: string和多个连接

qdi*_*dii 4 c++ string optimization std

让我们考虑一下这个片段,请假设a,b,c和d是非空字符串.

    std::string a, b, c, d;
    d = a + b + c;
Run Code Online (Sandbox Code Playgroud)

当计算这3个std::string实例的总和时  ,标准库实现创建第一个临时std::string对象,在其内部缓冲区中复制a和的连接缓冲区b,然后在临时字符串和之间执行相同的操作c.

一位同事程序员强调,operator+(std::string, std::string)可以定义为返回a 而不是此行为std::string_helper.

这个对象的作用是将实际的连接推迟到它被转换为a的那一刻std::string.显然,operator+(std::string_helper, std::string)将被定义为返回相同的帮助程序,这将"牢记"它有一个额外的串联来执行的事实.

这样的行为可以节省创建n-1临时对象,分配缓冲区,复制它们等的CPU成本.所以我的问题是:为什么它不能像那样工作?我想不出任何缺点或限制.

Mik*_*our 6

为什么它不像那样工作?

我只能推测为什么它最初是这样设计的.也许字符串库的设计者根本没有想到它; 也许他们认为额外的类型转换(见下文)可能会使某些情况下的行为过于令人惊讶.它是最古老的C++库之一,我们认为理所当然的许多智慧在过去几十年中根本不存在.

至于为什么它没有被改变为这样工作:它可以通过添加额外的用户定义类型转换来破坏现有代码.隐式转换最多只能涉及一个用户定义的转换.这是由C++ 11,13.3.3.1.2/1指定的:

用户定义的转换序列包括初始标准转换序列,后跟用户定义的转换,然后是第二个标准转换序列.

考虑以下:

struct thingy {
    thingy(std::string);
};

void f(thingy);

f(some_string + another_string);
Run Code Online (Sandbox Code Playgroud)

此代码是好的,如果类型some_string + another_stringstd::string.这可以thingy通过转换构造函数隐式转换为.但是,如果我们要更改定义operator+以提供另一种类型,那么它将需要两次转换(string_helperto stringto thingy),因此无法编译.

因此,如果字符串构建的速度很重要,则需要使用其他方法,例如串联+=.或者,根据Matthieu的回答,不要担心它,因为C++ 11以不同的方式修复了低效率.

  • 当我学习C++(大约1990年)时,这项技术很有名,所以我怀疑原因是原设计师没有听说过它.更有可能的是,他认为`std :: string`的典型用途是糟糕的设计. (2认同)

Jam*_*nze 6

显而易见的答案:因为标准不允许它.它在某些情况下通过引入额外的用户定义转换来影响代码:如果C是具有用户定义的构造函数的类型,std::string则会产生:

C obj = stringA + stringB;
Run Code Online (Sandbox Code Playgroud)

非法.