string += s1 和 string = string + s1 的区别
Difference between string += s1 and string = string + s1
当我使用fans = fans + s[i]
时,我的一个程序超过了时间限制,而当我使用fans += s[i]
时,它正在被接受...为什么会这样?
为了解释更多,fans 是一个字符串,s 也是一个字符串,所以在遍历字符串 s 时我只想要 s 的一些字符,所以我正在创建一个新字符串 fans.Now 有两种方法可以将字符添加到我的新的弦乐迷。问题如下
fans = fans + s[i]; // gives Time limit exceeded
fans += s[i]; // runs successfully
对于built-in类型 a += b
与a = a + b
完全一样(除了a
只计算一次) ,但对于 类,这些运算符被重载并调用不同的函数。
在您的示例中,fans = fans + s[i]
创建一个临时字符串,并将其分配(移动)到 fans
,但 fans += s[i]
不会创建该临时字符串,因此它可能更快。
std::string
有成员 operator +
和 operator +=
。前者通常通过中间临时的方式与后者一起实施。看起来像这样(如果您想确切了解您的实现源,请检查您的实现源):
/// note reference return type
std::string& operator +=(char c)
{
this->append(c);
return *this;
}
// note value return type
std::string operator +(char c) const
{
std::string tmp = *this;
tmp += c; // or just tmp.append(c) directly
return tmp;
}
tmp
的设置很昂贵。整体功能可以(通常是)通过 move-assignment 语义到 caller-side 上的最终目的地变得更好,但是临时的开销是 none-the-less 还在那里。多做几次,你不会注意到有什么不同。执行数千次或数百万次等,这可能意味着 world 的差异。
如果你使用fans=fans+s[i]
,字符串将在每次循环中被复制。新元素将添加到字符串的副本中,结果将重新分配给变量 fans
。在此之后,必须删除旧字符串,因为它不再被引用。这需要很多时间。
如果你使用扩充赋值fans+=s[i]
,字符串将不会在每次循环中都被复制,并且不需要删除引用变量,因为这里没有引用变量。这样可以节省很多时间。
希望你现在明白了!!
对于基本类型,a = a + b
和 a += b
意思相同。
对于任意class类型,a = a + b
和a += b
是不相关的;他们查找不同的运算符,而这些运算符可以做任意事情。它们 实际上 无关的是代码异味,这是设计问题的标志。
a = a + b
大致变成了 operator=( a, operator+( a, b ) )
;实际查找规则有点复杂(涉及成员运算符和 non-member 运算符,以及 =
没有 non-member 运算符等事实),但这是核心
a += b
变成 operator+=( a, b )
类似的意思。
现在,根据 +=
来实现 +
是一种常见的模式;如果你这样做,你会得到:
a = a + b
变成
a = ((auto)(a) += b);
其中 (auto)
是新的 c++20/c++23 "create a temporary copy of the argument" 功能。
从根本上说,a+=b
可以直接复用a
的内容,而a = a + b
则不能;目前 a+b
正在评估,它不知道 a
将很快被覆盖。
一些图书馆使用一种称为 "expression templates" 的技术来处理这个问题; a+b
不是一个值,而是表达式 a+b
的 compile-time 描述,当分配给 a
时,它实际上用于用数据填充 a
.使用表达式模板,消除了 a+=b
知道的比 a=a+b
多的根本问题。
现在,对于 std::string
,a+b
创建一个临时字符串对象,然后 a=(a+b)
将其移动到 a
(它可以重用临时字符串的缓冲区object or buffer of a
, standard is silent on this matter).
a+=b
必须重新使用 a
缓冲区中的任何多余容量。所以如果你a.reserve(1<<30)
(10亿),a+=b
不能分配更多。
当我使用fans = fans + s[i]
时,我的一个程序超过了时间限制,而当我使用fans += s[i]
时,它正在被接受...为什么会这样?
为了解释更多,fans 是一个字符串,s 也是一个字符串,所以在遍历字符串 s 时我只想要 s 的一些字符,所以我正在创建一个新字符串 fans.Now 有两种方法可以将字符添加到我的新的弦乐迷。问题如下
fans = fans + s[i]; // gives Time limit exceeded
fans += s[i]; // runs successfully
对于built-in类型 a += b
与a = a + b
完全一样(除了a
只计算一次) ,但对于 类,这些运算符被重载并调用不同的函数。
在您的示例中,fans = fans + s[i]
创建一个临时字符串,并将其分配(移动)到 fans
,但 fans += s[i]
不会创建该临时字符串,因此它可能更快。
std::string
有成员 operator +
和 operator +=
。前者通常通过中间临时的方式与后者一起实施。看起来像这样(如果您想确切了解您的实现源,请检查您的实现源):
/// note reference return type
std::string& operator +=(char c)
{
this->append(c);
return *this;
}
// note value return type
std::string operator +(char c) const
{
std::string tmp = *this;
tmp += c; // or just tmp.append(c) directly
return tmp;
}
tmp
的设置很昂贵。整体功能可以(通常是)通过 move-assignment 语义到 caller-side 上的最终目的地变得更好,但是临时的开销是 none-the-less 还在那里。多做几次,你不会注意到有什么不同。执行数千次或数百万次等,这可能意味着 world 的差异。
如果你使用fans=fans+s[i]
,字符串将在每次循环中被复制。新元素将添加到字符串的副本中,结果将重新分配给变量 fans
。在此之后,必须删除旧字符串,因为它不再被引用。这需要很多时间。
如果你使用扩充赋值fans+=s[i]
,字符串将不会在每次循环中都被复制,并且不需要删除引用变量,因为这里没有引用变量。这样可以节省很多时间。
希望你现在明白了!!
对于基本类型,a = a + b
和 a += b
意思相同。
对于任意class类型,a = a + b
和a += b
是不相关的;他们查找不同的运算符,而这些运算符可以做任意事情。它们 实际上 无关的是代码异味,这是设计问题的标志。
a = a + b
大致变成了 operator=( a, operator+( a, b ) )
;实际查找规则有点复杂(涉及成员运算符和 non-member 运算符,以及 =
没有 non-member 运算符等事实),但这是核心
a += b
变成 operator+=( a, b )
类似的意思。
现在,根据 +=
来实现 +
是一种常见的模式;如果你这样做,你会得到:
a = a + b
变成
a = ((auto)(a) += b);
其中 (auto)
是新的 c++20/c++23 "create a temporary copy of the argument" 功能。
从根本上说,a+=b
可以直接复用a
的内容,而a = a + b
则不能;目前 a+b
正在评估,它不知道 a
将很快被覆盖。
一些图书馆使用一种称为 "expression templates" 的技术来处理这个问题; a+b
不是一个值,而是表达式 a+b
的 compile-time 描述,当分配给 a
时,它实际上用于用数据填充 a
.使用表达式模板,消除了 a+=b
知道的比 a=a+b
多的根本问题。
现在,对于 std::string
,a+b
创建一个临时字符串对象,然后 a=(a+b)
将其移动到 a
(它可以重用临时字符串的缓冲区object or buffer of a
, standard is silent on this matter).
a+=b
必须重新使用 a
缓冲区中的任何多余容量。所以如果你a.reserve(1<<30)
(10亿),a+=b
不能分配更多。