Hầu hết các triển khai std::string
(bao gồm GCC) sử dụng tối ưu hóa chuỗi nhỏ. Ví dụ. có một số answer thảo luận về điều này.Không tối ưu hóa chuỗi nhỏ với gcc?
Hôm nay, tôi quyết định kiểm tra xem một chuỗi trong mã tôi biên dịch được chuyển đến vùng nào. Trước sự ngạc nhiên của tôi, mã thử nghiệm của tôi dường như cho thấy không có tối ưu hóa chuỗi nhỏ nào xảy ra!
Code:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) {
std::string s;
cout << "capacity: " << s.capacity() << endl;
cout << (void*)s.c_str() << " | " << s << endl;
for (int i=0; i<33; ++i) {
s += 'a';
cout << (void*)s.c_str() << " | " << s << endl;
}
}
Kết quả của g++ test.cc && ./a.out
là
capacity: 0
0x7fe405f6afb8 |
0x7b0c38 | a
0x7b0c68 | aa
0x7b0c38 | aaa
0x7b0c38 | aaaa
0x7b0c68 | aaaaa
0x7b0c68 | aaaaaa
0x7b0c68 | aaaaaaa
0x7b0c68 | aaaaaaaa
0x7b0c98 | aaaaaaaaa
0x7b0c98 | aaaaaaaaaa
0x7b0c98 | aaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0d28 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Tôi đoán rằng con trỏ đầu tiên lớn hơn, tức là 0x7fe405f6afb8
là một con trỏ ngăn xếp, và những người khác trỏ đến đống . Chạy nhiều lần này tạo ra kết quả giống hệt nhau, theo nghĩa là địa chỉ đầu tiên luôn lớn, và các địa chỉ còn lại nhỏ hơn; các giá trị chính xác thường khác nhau. Các địa chỉ nhỏ hơn luôn tuân theo sức mạnh chuẩn của 2 lược đồ phân bổ, ví dụ: 0x7b0c38
được liệt kê một lần, sau đó 0x7b0c68
được liệt kê một lần, sau đó 0x7b0c38
hai lần, sau đó 0x7b0c68
4 lần, sau đó 0x7b0c98
8 lần, vv
Sau khi đọc câu trả lời Howard, sử dụng một máy 64bit, tôi đã mong đợi để xem cùng một địa chỉ in cho 22 ký tự đầu tiên, và chỉ sau đó mới thấy nó thay đổi.
Tôi có thiếu gì đó không?
Ngoài ra, thú vị, nếu tôi biên dịch với -O
(ở bất kỳ cấp độ), tôi nhận được một hằng số nhỏ giá trị con trỏ 0x6021f8
trong trường hợp đầu tiên, thay vì giá trị lớn, và 0x6021f8
này không thay đổi bất kể bao nhiêu lần Tôi chạy chương trình.
Sản lượng g++ -v
:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/foo/bar/gcc-6.2.0/gcc/libexec/gcc/x86_64-redhat-linux/6.2.0/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../gcc-6.2.0/configure --prefix=/foo/bar/gcc-6.2.0/gcc --build=x86_64-redhat-linux --disable-multilib --enable-languages=c,c++,fortran --with-default-libstdcxx-abi=gcc4-compatible --enable-bootstrap --enable-threads=posix --with-long-double-128 --enable-long-long --enable-lto --enable-__cxa_atexit --enable-gnu-unique-object --with-system-zlib --enable-gold
Thread model: posix
gcc version 6.2.0 (GCC)
'--with-default-libstdcxx-abi = gcc4 tương thích' –
@ T.C. Có thật không? 'gcc4' không có tối ưu hóa chuỗi nhỏ? – SU3
Tôi nghĩ rằng tôi nhớ rằng tối ưu hóa chuỗi nhỏ đã được đưa (trở lại) vào ngôn ngữ – xaxxon