Saya telah melakukan beberapa optimasi yang dibutuhkan belakangan ini. Satu hal yang telah saya lakukan adalah mengubah beberapa ostringstreams -> sprintfs. Saya sprintf'ing banyak std :: string ke ac style array, ala
char foo[500];
sprintf(foo, "%s+%s", str1.c_str(), str2.c_str());
Ternyata implementasi std :: string :: c_str () Microsoft berjalan dalam waktu konstan (hanya mengembalikan pointer internal). Tampaknya libstdc ++ melakukan hal yang sama . Saya menyadari std tidak memberikan jaminan untuk c_str, tetapi sulit membayangkan cara lain untuk melakukan ini. Jika, misalnya, mereka menyalin ke dalam memori mereka juga harus mengalokasikan memori untuk buffer (menyerahkannya kepada pemanggil untuk menghancurkannya - BUKAN bagian dari kontrak STL) ATAU mereka harus menyalin ke statis internal buffer (mungkin bukan threadsafe, dan Anda tidak memiliki jaminan seumur hidup). Jadi hanya mengembalikan pointer ke string yang diakhiri dengan null yang dipelihara secara internal tampaknya menjadi satu-satunya solusi yang realistis.
sumber
c_str
metode const (atau setidaknya memiliki overload const - saya lupa yang mana), ini tidak mengubah nilai logis, jadi mungkin merupakan alasan untuk itumutable
. Ini akan memecah pointer dari panggilan lain kec_str
, kecuali bahwa setiap pointer tersebut harus merujuk ke string logis yang sama (jadi tidak ada alasan baru untuk realokasi - pasti sudah ada terminator nol) atau ada harus sudah ada panggilan ke non Metode -const di antara keduanya.c_str
panggilan dapat menjadi O (n) waktu untuk realokasi dan penyalinan. Tetapi ada juga kemungkinan bahwa ada aturan tambahan dalam standar yang saya tidak sadari akan mencegah hal ini. Alasan saya menyarankannya - panggilan kec_str
tidak benar-benar dimaksudkan untuk menjadi AFAIK biasa, sehingga mungkin tidak dianggap penting untuk memastikan mereka cepat - menghindari byte penyimpanan ekstra untuk terminator nol yang biasanya tidak perlu dalamstring
hal yang tidak pernah digunakanc_str
mungkin telah diutamakan.Boost.Format
internal melewati stream yang internal melewatisprintf
berakhir dengan overhead yang agak besar. Dokumentasi mengatakan itu sekitar 8 kali lebih lambat daripada biasasprintf
. Jika Anda ingin kinerja dan keamanan jenis, cobaBoost.Spirit.Karma
.Boost.Spirit.Karma
adalah tip yang baik untuk kinerja, tetapi berhati-hatilah karena ia memiliki metodologi yang sangat berbeda yang mungkin sulit untuk mengadaptasiprintf
kode gaya yang ada (dan coders). Saya sebagian besar terjebak denganBoost.Format
karena I / O kami tidak sinkron; tetapi faktor besar adalah bahwa saya dapat meyakinkan kolega saya untuk menggunakannya secara konsisten (masih memungkinkan jenis apa pun denganostream<<
kelebihan beban - yang dengan baik mengesampingkan.c_str()
perdebatan) Angka kinerja Karma .Dalam standar c ++ 11 (saya membaca versi N 3290), bab 21.4.7.1 berbicara tentang metode c_str ():
const charT* c_str() const noexcept; const charT* data() const noexcept;
Jadi, ya: kompleksitas waktu konstan dijamin oleh standar.
Saya baru saja memeriksa c ++ 03 standar, dan tidak memiliki persyaratan seperti itu, juga tidak memberitahu kompleksitasnya.
sumber
Dalam teori C ++ 03 tidak mengharuskan itu, dan karenanya string dapat berupa array char di mana keberadaan terminator nol ditambahkan hanya pada saat c_str () dipanggil. Ini mungkin memerlukan realokasi (itu tidak melanggar konstanta, jika pointer pribadi internal dinyatakan sebagai
mutable
).C ++ 11 lebih ketat: membutuhkan waktu yang mahal, jadi tidak ada relokasi yang dapat dilakukan dan array harus selalu cukup lebar untuk menyimpan null pada akhirnya. c_str (), dengan sendirinya, masih dapat melakukan "
ptr[size()]='\0'
" untuk memastikan null benar-benar ada. Itu tidak melanggar konstanta array karena rentang[0..size())
tidak berubah.sumber