2016-12-22 11 views
6

Tôi có một phương pháp mất std::string_view và sử dụng chức năng, trong đó có null chấm dứt chuỗi như tham số. Ví dụ:Sử dụng std :: string_view với api, những gì mong đợi null chấm dứt chuỗi

void stringFunc(std::experimental::string_view str) { 
    some_c_library_func(/* Expects null terminated string */); 
} 

Câu hỏi là, cách thích hợp để xử lý tình huống này là gì? Có phải str.to_string().c_str() là tùy chọn duy nhất không? Và tôi thực sự muốn sử dụng std::string_view trong phương pháp này, bởi vì tôi vượt qua các loại chuỗi khác nhau trong đó.

Trả lời

4

Bạn không thể thay đổi một chuỗi thông qua std::string_view. Do đó bạn không thể thêm ký tự kết thúc '\0'. Do đó bạn cần phải sao chép chuỗi ở một nơi khác để thêm một '\0' -terminator. Bạn có thể tránh phân bổ đống bằng cách đặt chuỗi trên ngăn xếp, nếu nó đủ ngắn. Nếu bạn biết, rằng std::string_view là một phần của một chuỗi null chấm dứt, sau đó bạn có thể kiểm tra, nếu ký tự qua cuối cùng là một ký tự '\0' và tránh bản sao trong trường hợp đó. Ngoài ra, tôi không còn nhiều chỗ để tối ưu hóa.

+0

sử dụng tốt cho VLA. – user1095108

+4

@ user1095108 nhưng bất kỳ trình biên dịch nào cho phép VLAs trong C++ đang áp dụng một phần mở rộng không chuẩn, vì vậy tôi sẽ nói VLAs không bao giờ có thể tốt đẹp. : P –

+0

Chúng thực sự được hỗ trợ ở khắp mọi nơi thông qua alloca, bạn có thể làm cho chúng di động – user1095108

4

Bạn chắc chắn không nên gọi data trên std::experimental::string_view:

Không giống như basic_string :: dữ liệu() và chuỗi literals, dữ liệu() có thể trả về một con trỏ đến một bộ đệm đó không phải là null-chấm dứt.

Vì vậy, gọi to_stringdata trên rằng:

void stringFunc(std::experimental::string_view str) { 
    some_c_library_func(str.to_string().data()); 
} 

hay:

void stringFunc(std::experimental::string_view str) { 
    std::string real_str(str); 
    some_c_library_func(real_str.data()); 
} 
8

Tôi đã giải quyết vấn đề này bằng cách tạo một lớp thay thế string_view có tên là zstring_view. Nó được thừa hưởng riêng từ string_view và chứa nhiều giao diện của nó.

Sự khác biệt nguyên tắc là không thể tạo zstring_view từ string_view. Ngoài ra, mọi API string_view sẽ xóa các phần tử khỏi phần kết thúc không phải là một phần của giao diện hoặc chúng trả lại string_view thay vì zstring_view.

Chúng có thể được tạo từ bất kỳ nguồn chuỗi nào được kết thúc bằng NUL: std::string v.v. Tôi thậm chí còn tạo hậu tố chữ đặc biệt do người dùng xác định cho chúng: _zsv.

Ý tưởng là, miễn là bạn không đặt một chuỗi không được NUL chấm dứt vào zstring_view theo cách thủ công, tất cả zstring_view s phải được NUL chấm dứt. Giống như std::string, ký tự NUL không phải là một phần của kích thước của chuỗi, nhưng nó là .

Tôi thấy nó rất hữu ích để xử lý giao tiếp C.

+0

Tôi chỉ làm như vậy, và tôi đồng ý giao diện rất đẹp và loại bỏ lý do cuối cùng bao giờ làm const std :: string & as a parameter.Bạn mất rất nhiều tiện lợi bằng cách sử dụng quyền thừa kế riêng tư (như so sánh, và chuyển đổi về string_view) - nhìn vào giao diện, có vẻ như các mutator có vấn đề chỉ loại bỏ _ *** fix và swap - tôi chỉ reimplemented swap và thêm remove_ *** sửa thành các thành viên không được triển khai riêng tư và mọi thứ dường như hoạt động tốt - vì vậy bạn thực sự có thể kế thừa công khai từ std :: string_view. Chỉ có vấn đề là các trình biến thể mới được thêm vào string_view trong tương lai. – Shaggi

+0

Mặc dù có thể nói đó là kiểu xấu. Ngoài ra, bạn sẽ gặp phải vấn đề khi chuyển zstring_views thành các hàm lấy string_view & (điều kỳ lạ theo hai cách ...) – Shaggi

Các vấn đề liên quan