§21.4.5 [string.access]
Là một std :: chuỗi thực hiện conformant nơi 's.c_str() + s.size()' không nhất thiết phải giống như '& s [s.size()]'?
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Returns:
*(begin() + pos)
nếupos < size()
. Nếu không, trả về một tham chiếu đến một đối tượng thuộc loạicharT
với giá trịcharT()
, nơi sửa đổi đối tượng dẫn đến hành vi không xác định.
Phần thứ hai ngụ ý, với tôi ít nhất, rằng "đối tượng kiểu charT
" này có thể nằm ngoài chuỗi được lưu trữ trong đối tượng std::string
. thực hiện ví dụ về một phù hợp operator[]
:
reference operator[](size_type pos){
static contexpr charT default = charT();
if(pos == size())
return default;
return buf[pos];
}
Bây giờ, c_str()
/data()
, được quy định tại các điều khoản của operator[]
:
§21.4.7 [string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;
Returns: Một con trỏ
p
như vậyp + i == &operator[](i)
cho mỗii
trong[0,size()]
.
Điều này sẽ làm cho việc triển khai trên operator[]
không phù hợp, như p + size() != &operator[](size())
. Tuy nhiên, với một chút thủ đoạn gian trá, bạn có thể phá vỡ vấn đề này:
reference operator[](size_type pos){
static contexpr charT default = charT();
if(pos == size() && !evil_context) // assume 'volatile bool evil_context;'
return default;
return buf[pos];
}
struct evil_context_guard{
volatile bool& ctx;
evil_context_guard(volatile bool& b)
: ctx(b) {}
~evil_context_guard(){ b = false; }
};
const charT* c_str() const noexcept{
evil_context_guard g(evil_context = true);
// now, during the call to 'c_str()', the requirement above holds
// 'p + i == &operator[](i) for each i in [0,size()]'
const charT* p = &buf[0];
assert(p+size() == &operator[](size()));
return p;
}
Bây giờ, câu hỏi rõ ràng là ...
Là mã trên thực sự tuân thủ QTI hoặc tôi đã bỏ qua một cái gì đó?
Một điều tôi nhận thấy là nếu bạn thực sự viết kiểm tra cho một đối tượng chuỗi 'str':' char * p = str.c_str(); size_t i = str.size(); khẳng định (p + i == & str [i]); 'xác nhận sẽ thất bại với mã của bạn. Tiêu chuẩn dường như không chỉ định một bối cảnh cụ thể mà bất biến phải giữ, vì vậy tôi sẽ cẩn thận về việc giả sử nó chỉ cần giữ trước khi 'c_str()' trả về. – pmdj