簡體   English   中英

高效的自定義字符串創建器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM