std::operator+(std::basic_string)

来自cppreference.com
< cpp‎ | string‎ | basic string
 
 
 
std::basic_string
成员函数
元素访问
迭代器
容量
修改器
搜索
操作
常量
非成员函数
operator+
I/O
比较
(C++20 前)(C++20 前)(C++20 前)(C++20 前)(C++20 前)(C++20)
数值转换
(C++11)(C++11)(C++11)
(C++11)(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
字面量
辅助类
推导指引 (C++17)

 
在标头 <string> 定义
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,

               const std::basic_string<CharT,Traits,Alloc>& rhs );
(1) (C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,

               const CharT* rhs );
(2) (C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,

               CharT rhs );
(3) (C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

constexpr std::basic_string<CharT,Traits,Alloc>
    operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,

               std::type_identity_t<std::basic_string_view<CharT,Traits>> rhs );
(4) (C++26 起)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const CharT* lhs,

               const std::basic_string<CharT,Traits,Alloc>& rhs );
(5) (C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( CharT lhs,

               const std::basic_string<CharT,Traits,Alloc>& rhs );
(6) (C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

constexpr std::basic_string<CharT,Traits,Alloc>
    operator+( std::type_identity_t<std::basic_string_view<CharT,Traits>> lhs,

               const std::basic_string<CharT,Traits,Alloc>& rhs );
(7) (C++26 起)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,

               std::basic_string<CharT,Traits,Alloc>&& rhs );
(8) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,

               const std::basic_string<CharT,Traits,Alloc>& rhs );
(9) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,

               const CharT* rhs );
(10) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,

               CharT rhs );
(11) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

constexpr std::basic_string<CharT,Traits,Alloc>
    operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,

               std::type_identity_t<std::basic_string_view<CharT,Traits>> rhs );
(12) (C++26 起)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,

               std::basic_string<CharT,Traits,Alloc>&& rhs );
(13) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( const CharT* lhs,

               std::basic_string<CharT,Traits,Alloc>&& rhs );
(14) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

std::basic_string<CharT,Traits,Alloc>
    operator+( CharT lhs,

               std::basic_string<CharT,Traits,Alloc>&& rhs );
(15) (C++11 起)
(C++20 起为 constexpr)
template< class CharT, class Traits, class Alloc >

constexpr std::basic_string<CharT,Traits,Alloc>
    operator+( std::type_identity_t<std::basic_string_view<CharT,Traits>> lhs,

               std::basic_string<CharT,Traits,Alloc>&& rhs );
(16) (C++26 起)

返回含有来自 lhs 的字符后随来自 rhs 的字符的字符串。等价于:

1,2) std::basic_string<CharT, Traits, Allocator> r = lhs; r.append(rhs); return r;
3) std::basic_string<CharT, Traits, Allocator> r = lhs; r.push_back(rhs); return r;
4) std::basic_string<CharT, Traits, Allocator> r = lhs; r.append(rhs); return r;
5) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(0, lhs); return r;
6) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(r.begin(), lhs); return r;
7) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(0, lhs); return r;
8) lhs.append(rhs); return std::move(lhs);,但 lhsrhs 都留在有效但未指明的状态。如果 lhsrhs 有相等的分配器,则实现可以从任何一个移动。
9,10) lhs.append(rhs); return std::move(lhs);
11) lhs.push_back(rhs); return std::move(lhs);
12) lhs.append(rhs); return std::move(lhs);
13,14) rhs.insert(0, lhs); return std::move(rhs);
15) rhs.insert(rhs.begin(), lhs); return std::move(rhs);
16) rhs.insert(0, lhs); return std::move(rhs);


结果所用的分配器为:

1-4) std::allocator_traits<Alloc>::select_on_container_copy_construction(lhs.get_allocator())
5-7) std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.get_allocator())
8-12) lhs.get_allocator()
13-16) rhs.get_allocator()

换言之:

  • 若操作数之一是 basic_string 右值,则使用其分配器。
  • 否则在左值 basic_string 操作数的分配上使用 select_on_container_copy_construction

每种情况下,当两者是拥有同一值类别的 basic_string 时,偏向左操作数。

(8-16) 将所有右值 basic_string 操作数置于合法但未指定的状态。

(C++11 起)

参数

lhs - 字符串、字符串视图 (C++26 起)、字符或指向空终止字符序列首字符的指针
rhs - 字符串、字符串视图 (C++26 起)、字符或指向空终止字符序列首字符的指针

返回值

含有来自 lhs 的字符后随来自 rhs 的字符的字符串,使用如上确定的分配器 (C++11 起)

注解

涉及有状态分配器时(例如用 std::pmr::string 时) (C++17 起),应该谨慎使用 operator+。在 P1165R1 前,确定结果所用的分配器是历史事故,它在不同重载间无显著理由地变换。另外,对于 (1-5),分配器传播行为在主流标准库实现间各异,且异于标准所描述的行为。

operator+ 的结果所用的分配器对值类别敏感,故 operator+ 相对于分配器传播不满足结合律:

using my_string = std::basic_string<char, std::char_traits<char>, my_allocator<char>>;
my_string cat();
const my_string& dog();
 
my_string meow = /* ... */, woof = /* ... */;
meow + cat() + /*...*/; // 使用 meow 的分配器上的 select_on_container_copy_construction
woof + dog() + /*...*/; // 转而使用 dog() 的返回值的分配器
 
meow + woof + meow; // 使用 meow 的分配器上的 SOCCC
meow + (woof + meow); // 转而使用 woof 的分配器上的 select_on_container_copy_construction

对于 operator+ 的调用链,可通过前置拥有所欲分配器的右值 basic_string 来控制最终结果所用的分配器:

// 令最终结果使用 my_favorite_allocator
my_string(my_favorite_allocator) + meow + woof + cat() + dog();

为了更好且可移植地对分配器进行控制,应该在以所欲分配器构造的结果字符串上,使用 append()insert()operator+=() 之类的成员函数。

(C++11 起)

根据重载决议规则,使用 std::type_identity_t 作为重载 (4)(7)(12)(16) 的形参,保证了 std::basic_string<CharT, Traits, Allocator> 类型的对象总是可以与能够隐式转换为 std::basic_string_view<CharT, Traits>T 类型的对象进行连接,反之亦然。

功能特性测试 标准 功能特性
__cpp_lib_string_view 202403 (C++26) 连接字符串和字符串视图,重载 (4)(7)(12)(16)
(C++26 起)

示例

#include <iostream>
#include <string>
#include <string_view>
 
int main()
{
    std::string s1 = "Hello";
    std::string s2 = "world";
    const char* end = "!\n";
    std::cout << s1 + ' ' + s2 + end;
 
    std::string_view water{" Water"};
    #if __cpp_lib_string_view >= 202403
    std::cout << s1 + water + s2 << end; // 重载 (4),然后重载 (1)
    #else
    std::cout << s1 + std::string(water) + s2 << end; // OK,但较低效
    #endif
}

输出:

Hello world!
Hello Waterworld!

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
P1165R1 C++11 分配器传播混乱且不一致 使之更为一致

参阅

后附字符到结尾
(公开成员函数)
后附字符到结尾
(公开成员函数)
插入字符
(公开成员函数)