std::string_view
là nhanh hơn trong một vài trường hợp.
Đầu tiên, std::string const&
yêu cầu dữ liệu phải ở trong một std::string
, chứ không phải mảng C thô, được char const*
trả về bởi API C, std::vector<char>
được tạo bởi một số công cụ khử lưu huỳnh, v.v. Việc chuyển đổi định dạng tránh sẽ tránh sao chép byte và (nếu chuỗi dài hơn SBO¹ cho việc std::string
thực hiện cụ thể ) tránh phân bổ bộ nhớ.
void foo( std::string_view bob ) {
std::cout << bob << "\n";
}
int main(int argc, char const*const* argv) {
foo( "This is a string long enough to avoid the std::string SBO" );
if (argc > 1)
foo( argv[1] );
}
Không có phân bổ được thực hiện trong string_view
trường hợp, nhưng sẽ có nếu foo
lấy một std::string const&
thay vì a string_view
.
Lý do thực sự lớn thứ hai là nó cho phép làm việc với các chuỗi con mà không cần một bản sao. Giả sử bạn đang phân tích chuỗi json 2 gigabyte (!) ². Nếu bạn phân tích cú pháp đó std::string
, mỗi nút phân tích cú pháp như vậy nơi họ lưu trữ tên hoặc giá trị của một nút sẽ sao chép dữ liệu gốc từ chuỗi 2 gb sang một nút cục bộ.
Thay vào đó, nếu bạn phân tích nó thành std::string_view
s, các nút tham chiếu đến dữ liệu gốc. Điều này có thể tiết kiệm hàng triệu phân bổ và giảm một nửa yêu cầu bộ nhớ trong khi phân tích cú pháp.
Việc tăng tốc bạn có thể nhận được chỉ đơn giản là vô lý.
Đây là một trường hợp cực đoan, nhưng các trường hợp "lấy một chuỗi con và làm việc với nó" khác cũng có thể tạo ra các tốc độ khá tốt với string_view
.
Một phần quan trọng cho quyết định là những gì bạn mất bằng cách sử dụng std::string_view
. Nó không nhiều, nhưng nó là một cái gì đó.
Bạn mất kết thúc null ẩn, và đó là về nó. Vì vậy, nếu cùng một chuỗi sẽ được chuyển đến 3 hàm, tất cả đều yêu cầu một bộ kết thúc null, chuyển đổi thành std::string
một lần có thể là khôn ngoan. Do đó, nếu mã của bạn được biết là cần một bộ kết thúc null và bạn không mong đợi các chuỗi được cung cấp từ bộ đệm có nguồn gốc kiểu C hoặc tương tự, có thể mất một std::string const&
. Nếu không thì lấy a std::string_view
.
Nếu std::string_view
có một cờ cho biết nếu nó bị hủy kết thúc (hoặc một cái gì đó lạ hơn) thì nó sẽ xóa ngay cả lý do cuối cùng để sử dụng a std::string const&
.
Có một trường hợp lấy std::string
không có const&
là tối ưu hơn a std::string_view
. Nếu bạn cần sở hữu một bản sao của chuỗi vô thời hạn sau cuộc gọi, lấy theo giá trị là hiệu quả. Bạn sẽ ở trong trường hợp SBO (và không phân bổ, chỉ cần một vài bản sao ký tự để sao chép nó) hoặc bạn sẽ có thể di chuyển bộ đệm được phân bổ heap thành cục bộ std::string
. Có hai lần quá tải std::string&&
và std::string_view
có thể nhanh hơn, nhưng chỉ một chút, và nó sẽ gây ra sự phình to mã khiêm tốn (có thể khiến bạn mất tất cả các mức tăng tốc độ).
Optimization Tối ưu hóa bộ đệm nhỏ
² Trường hợp sử dụng thực tế.
std::string_view
chỉ là một sự trừu tượng của cặp (char * started, char * end). Bạn sử dụng nó khi tạo mộtstd::string
bản sao không cần thiết.