[英]Efficient custom string creator
我想知道傳遞自定義字符串最有效的方法是什么。 例如,我有以下代碼段:
outputFile << addSpace(data.len());
哪里
string addSpace(int n) {
string result("");
for (int i = 0; i < n; i++) {
result += ' ';
}
return result;
}
顯然,該功能不是很有效,因為該字符串是按val返回的,然后甚至可以在適合RValue的地方使用。 如果N是固定的,例如N = 5,我可以使用
outputFile << " "
但顯然並非如此。
那么什么是最好的解決方案呢(不管這個N個空格的具體例子如何,對於任何依賴於參數的字符串創建來說都是如此)。 我考慮過lambda函數,但我不確定。
很明顯,該函數不是很有效,因為該字符串是按val返回的。
該字符串是本地字符串,因此按值返回是唯一的選擇。 並不是真正的按值返回會使函數效率降低,而是在每個調用中創建一個新字符串的事實。 必須按值返回的事實只是該設計的一個症狀。 但是,除非您多次調用不同n
的函數(否則,調用方使用相同的n
,他們可以保留返回的字符串並重用它),否則效率低下可能是微不足道的。
您當然可以將對字符串的引用傳遞給該函數,讓該函數修改該字符串,然后返回該引用,如果使用相同的參數字符串多次調用該函數,則的確確實(可能只是略微)有效。因為這樣可以避免在每次調用時都創建新的字符串。 但是隨后您需要在調用代碼中管理該外部字符串,這將使函數的使用更加復雜,因此變得更糟。 而且,如果您不重用參數字符串,那么它的效率將更高。
如果選擇為每個實例使用新的字符串,則比函數更簡單(並且可能更有效,但是比重用字符串的區別要大得多)。 只需使用std::string
的構造函數:
outputFile << std::string(data.len(), ' ');
在這種情況下,根本不創建字符串可能會更有效:
outputFile << std::setfill(' ') << std::setw(data.len()) << ' ';
因此,對於一般情況,選擇歸結為:效率比一個好的接口至關重要,並且字符串可以重用-然后將引用傳遞給字符串並進行修改。 否則,最好像您的示例那樣返回一個新字符串。
您可以使用string.insert函數。 函數可以從字符串的給定位置開始插入任意數量的字符。
字符串和插入(size_t pos,size_t n,char c);
參考: http : //www.cplusplus.com/reference/string/string/insert/
例:
string result = "foo";
int n = 5;
result.insert(result.length(), n, ' '); //result will become "foo "
我認為您的功能不是那么低效。 讓我們檢查潛在的低效率:
string::operator+=(char)
看起來很糟糕(對於自定義類型來說可能是這樣)。 但是對於字符串,它不會創建和分配新的字符串,它實際上只是將一個字符附加到現有的字符上。 追加一個字符應該具有恆定的時間復雜度。 如果您確實只需要在字符串中重復相同的字符,則user2079303的構造函數建議確實是創建它的正確方法。
通過價值回歸的結果:一個現代化的編譯器將移動串出的功能或構建其就地開始用,而不是創建臨時副本。 移動字符串也應該非常快(特別是,沒有(取消)分配動態內存)。
每次調用函數時動態分配一個字符串:這是效率低的部分。 如果您確實需要字符串(並且您的示例只是一個簡單的例子),則按照user2079303的建議,提交對預先存在的字符串的引用是解決此問題的一種好方法。 某些Java Swing API進行了一些修改,這些函數接受了預先存在的對象引用,以避免像示例中那樣對短期對象進行動態內存操作。
避免創建字符串的另一種方法是重新設計。 如果代碼確實與輸出有關,請向該函數提供一個ostream
引用,然后讓該函數決定如何最有效地輸出某些內容。 正如我所說,這取決於您的用例。
您可以返回包含足夠信息來執行io操作的內容
在這種情況下,您的addspace
可以變成
#include <iostream>
struct secret_thing_to_add_space{
int number;
};
std::ostream& operator << (std::ostream& os, const secret_thing_to_add_space& s){
//just use simple method here, you can use something different
for(int i=0;i<s.number;++i)os<<' ';
return os;
};
secret_thing_to_add_space addspace(int n){
return {n};
}
int main(){
std::cout<< "begin" << addspace(10) << "end";
}
如您所見,它變得復雜。 (並且在這種情況下不太可能更有效)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.