Không có cách nào để tránh một phiên bản std::string
tạm thời sao chép dữ liệu ký tự. Lưu ý rằng chi phí này rất thấp và không phải phân bổ bộ nhớ động nếu việc triển khai thư viện chuẩn của bạn sử dụng tối ưu hóa chuỗi ngắn.
Tuy nhiên, nếu bạn cần chuỗi proxy kiểu C thường xuyên, bạn vẫn có thể đưa ra các giải pháp tùy chỉnh sẽ vượt qua phân bổ này.Điều này có thể trả hết nếu bạn phải thực hiện điều này thực sự thường xuyên và các chuỗi của bạn đủ dài để không được hưởng lợi từ tối ưu hóa chuỗi ngắn.
Nếu bạn chỉ cần rất tập con nhỏ của chức năng chuỗi (ví dụ: chỉ gán và sao chép), thì bạn có thể viết một chuỗi chuỗi mục đích đặc biệt nhỏ lưu trữ con trỏ const char *
và chức năng giải phóng bộ nhớ.
class cheap_string
{
public:
typedef void(*Free)(const char*);
private:
const char * myData;
std::size_t mySize;
Free myFree;
public:
// direct member assignments, use with care.
cheap_string (const char * data, std::size_t size, Free free);
// releases using custom deleter (a no-op for proxies).
~cheap_string();
// create real copies (safety first).
cheap_string (const cheap_string&);
cheap_string& operator= (const cheap_string&);
cheap_string (const char * data);
cheap_string (const char * data, std::size_t size)
: myData(new char[size+1]), mySize(size), myFree(&destroy)
{
strcpy(myData, data);
myData[mySize] = '\0';
}
const char * data() const;
const std::size_t size() const;
// whatever string functionality you need.
bool operator< (const cheap_string&) const;
bool operator== (const cheap_string&) const;
// create proxies for existing character buffers.
static const cheap_string proxy (const char * data)
{
return cheap_string(data, strlen(data), &abandon);
}
static const cheap_string proxy (const char * data, std::size_t size)
{
return cheap_string(data, size, &abandon);
}
private:
// deleter for proxies (no-op)
static void abandon (const char * data)
{
// no-op, this is used for proxies, which don't own the data!
}
// deleter for copies (delete[]).
static void destroy (const char * data)
{
delete [] data;
}
};
Sau đó, bạn có thể sử dụng lớp này như:
std::map<cheap_string, int> m1;
auto i = m1.find(cheap_string::proxy("foo"));
Các tạm cheap_string
dụ không tạo ra một bản sao của bộ đệm nhân vật như std::string
không, nhưng nó bảo ngữ nghĩa bản sao an toàn để lưu trữ các trường hợp cheap_string
trong các thùng chứa tiêu chuẩn.
ghi chú: nếu thực hiện của bạn không sử dụng tối ưu hóa giá trị trả về, bạn sẽ muốn tìm một cú pháp thay thế cho phương pháp proxy
, chẳng hạn như một nhà xây dựng với một tình trạng quá tải đặc biệt (dùng một kiểu tùy chỉnh proxy_t
à la std::nothrow
cho vị trí mới).
Nếu bạn có thể thay đổi định nghĩa của bản đồ, bạn có thể sử dụng trình so sánh tùy chỉnh cho phép 'char const *' trực tiếp – Pablo
Bạn sẽ nhận được 'const char *' ở đâu? – Puppy
@Pablo: Nhưng sau đó .. ai đó sẽ phải quản lý một bộ nhớ mà các phím đang trỏ .. trừ khi họ là tất cả trong phân đoạn dữ liệu ... –