std::operator+(std::basic_string)

出自cppreference.com
< cpp‎ | string‎ | basic string
 
 
 
std::basic_string
 
在標頭 <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_view202403(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++ 標準。

缺陷報告應用於出版時的行為正確行為
P1165R1C++11分配器傳播混亂且不一致使之更為一致

[編輯] 參閱

後附字符到結尾
(公開成員函數) [編輯]
後附字符到結尾
(公開成員函數) [編輯]
插入字符
(公開成員函數) [編輯]