2011-04-23 38 views
5

Tôi đang cố gắng tìm hiểu thêm một chút về chuỗi C++.Hiểu hiệu quả của một tiêu chuẩn :: string

xem xét

const char* cstring = "hello"; 
std::string string(cstring); 

std::string string("hello"); 

Am I correct trong giả định rằng cả hai cửa hàng "hello" trong phần .data của một ứng dụng và các byte sau đó sao chép sang khu vực khác trên heap nơi con trỏ được quản lý bởi std :: string có thể truy cập chúng?

Làm cách nào để lưu trữ hiệu quả chuỗi dài thực sự? Tôi đang suy nghĩ về một ứng dụng đọc dữ liệu từ một dòng socket. Tôi sợ ghép nối nhiều lần. Tôi có thể tưởng tượng bằng cách sử dụng một danh sách liên kết và đi qua danh sách này.

Chuỗi đã đe dọa tôi quá lâu!

Mọi liên kết, mẹo, giải thích, chi tiết bổ sung, sẽ cực kỳ hữu ích.

+0

Thời gian thực sự dài bao lâu? 10 MB? 20 có lẽ? Hay bạn có ý nghĩa gì đó giống như 10 GB? Máy tính có gigabyte RAM trong những ngày này. –

+0

Tôi đã suy nghĩ nhiều hơn 10-100 MB. Tuy nhiên, điều này được dự định là một câu hỏi mở, vì vậy hãy giải thích một trong hai =). Tôi khá chắc chắn do quản lý bộ nhớ hệ điều hành bạn không thể phân bổ 10GB bộ nhớ tiếp giáp. Tôi giả định một danh sách sẽ được yêu cầu cho một kích thước như vậy. – flumpb

+1

@kispit - Trên máy tính 64 bit của tôi, tôi có thể cấp phát bộ nhớ cho đến khi tệp hoán đổi lấp đầy đĩa cứng. Hàng chục GB là không có vấn đề! –

Trả lời

2

Tôi đã lưu các chuỗi trong phạm vi 10 hoặc 100 của MB mà không gặp vấn đề gì. Đương nhiên, nó sẽ chủ yếu bị hạn chế bởi không gian bộ nhớ/địa chỉ sẵn có (liền kề) của bạn.

Nếu bạn sắp sửa nối/ghép nối, có một vài điều có thể giúp hiệu quả khôn ngoan: Nếu có thể, hãy thử sử dụng hàm thành viên dự phòng() để phân bổ trước không gian-- ngay cả khi bạn có ý tưởng sơ bộ về kích thước cuối cùng có thể lớn đến mức nào, nó sẽ tiết kiệm được từ việc phân phối lại không cần thiết khi chuỗi phát triển.

Ngoài ra, nhiều triển khai chuỗi sử dụng "tăng trưởng theo cấp số nhân", có nghĩa là chúng phát triển bởi một số phần trăm, thay vì kích thước byte cố định. Ví dụ, nó có thể đơn giản là gấp đôi dung lượng bất cứ lúc nào cần thêm không gian. Bằng cách tăng kích thước theo cấp số nhân, nó sẽ trở nên hiệu quả hơn để thực hiện nhiều kết nối. (Chi tiết chính xác sẽ phụ thuộc vào phiên bản của stl.)

Cuối cùng, một tùy chọn (nếu thư viện của bạn hỗ trợ nó) là sử dụng dây <> mẫu: Dây thừng cũng tương tự như chuỗi, ngoại trừ việc họ được nhiều hơn nữa hiệu quả khi thực hiện các thao tác trên các chuỗi rất lớn. Đặc biệt, "dây được phân bổ theo khối nhỏ, giảm đáng kể các vấn đề phân mảnh bộ nhớ được giới thiệu bởi các khối lớn". Một số chi tiết bổ sung trên SGI's STL guide.

+0

Tôi sẽ kiểm tra dây thừng, cảm ơn. – flumpb

0

Tôi không nghĩ rằng hiệu quả sẽ là vấn đề. Cả hai sẽ thực hiện đủ tốt.

Yếu tố quyết định ở đây là đóng gói. std::string là một trừu tượng tốt hơn nhiều so với char * có thể là bao giờ hết. Số học con trỏ đóng gói là một điều tốt.

Rất nhiều người đã suy nghĩ thật lâu và khó để tìm ra std::string. Tôi nghĩ rằng không sử dụng nó vì lý do hiệu quả vô căn cứ là ngu xuẩn. Dính vào trừu tượng tốt hơn và đóng gói.

+1

Tôi không nghĩ rằng nó không hợp lý để lo lắng về hiệu quả với các loại kích thước dữ liệu chúng tôi đang nói về ở đây; 'strcat' dẫn đến một giải pháp O (n^2) được bảo đảm có thể hiển thị chậm chạp. Có một cơ hội tốt 'string.append' có thể là O (n), tiêu chuẩn thậm chí có thể đảm bảo nó. –

+0

Thực tế là rất nhiều người suy nghĩ lâu dài và khó khăn về std :: string tiếc là không nói đến lợi thế của nó ... Đó là một trong những phần bị chỉ trích nhất của STL và vì lý do chính đáng, tôi nghĩ vậy. Các ngôn ngữ khác làm tốt hơn cho chuỗi. –

+0

@kotlinski: Tôi rất tò mò muốn đọc một số lời chỉ trích về std :: string. Có bất kỳ liên kết nào không? –

0

Như bạn đã biết, an std::string is really just another name for basic_string<char>.

Điều đó nói rằng, họ là một thùng chứa chuỗi và bộ nhớ sẽ được phân bổ theo tuần tự. Có thể nhận được một ngoại lệ từ một chuỗi std :: nếu bạn cố gắng tạo một ngoại lệ lớn hơn bộ nhớ liền kề sẵn có mà bạn có thể cấp phát.Ngưỡng này thường nhỏ hơn đáng kể so với tổng bộ nhớ có sẵn do phân mảnh bộ nhớ.

Tôi đã gặp sự cố phân bổ bộ nhớ tiếp giáp khi cố gắng cấp phát, ví dụ: bộ đệm 3D tiếp giáp lớn cho hình ảnh. Nhưng những vấn đề này không bắt đầu xảy ra ít nhất là theo thứ tự 100MB hoặc hơn, ít nhất là trong kinh nghiệm của tôi, trên Windows XP Pro (ví dụ.)

Dây của bạn có lớn không?

2

Vì bạn đang đọc chuỗi từ ổ cắm, bạn có thể tái sử dụng cùng một bộ đệm gói và nối chúng lại với nhau để biểu diễn chuỗi lớn. Điều này sẽ tránh được việc sao chép không cần thiết và có lẽ là giải pháp hiệu quả nhất có thể. Tôi dường như nhớ rằng thư viện ACE cung cấp một cơ chế như vậy. Tôi sẽ cố gắng tìm nó.

EDIT: ACE có ACE_Message_Block cho phép bạn lưu trữ thư lớn theo kiểu danh sách liên kết. Bạn hầu như cần đọc các cuốn sách Lập trình mạng C++ để hiểu về thư viện khổng lồ này. Các hướng dẫn miễn phí trên trang web ACE thực sự hút.

Tôi đặt cược Boost.Asio phải có khả năng thực hiện tương tự như khối tin nhắn của ACE. Boost.Asio bây giờ dường như có một mindshare lớn hơn ACE, vì vậy tôi đề nghị tìm kiếm một giải pháp trong Boost.Asio đầu tiên. Nếu bất cứ ai có thể khai sáng cho chúng tôi về một giải pháp Boost.Asio, điều đó thật tuyệt vời!


Đó là khoảng thời gian tôi cố gắng viết một ứng dụng client-server đơn giản sử dụng Boost.Asio để xem những gì tất cả các fuss là về.

+0

Tôi sẽ xem xét kỹ hơn điều này, cảm ơn bạn rất nhiều vì đã trả lời – flumpb

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