c++ 17 vector中string的性能問題 std::vector string vs string_view


1,C風格字符串一般以char* 或 char str[]表示,字符串以'\0'結尾

2,sizeof()獲得給定數據類型或變量的內存大小,strlen()獲得字符串長度

3,字符串字面量

char* arr = "hello"; arr[1] = 'b'; // 未定義行為,非法 char arr[] = "hello"; arr[1] = 'b'; // 可以修改 

4,原始字符串字面量

const char* str = R"(hello "world"!)" // 以R"(開頭,以)"結尾 

5,C++ std::string類

a, 重載了+、[]、==、!=、<、<= 等運算符
b, string類的c_str()方法可以獲得一個C風格的const char* c, 高級數值轉換與低級數值轉換

6. string_view (c++ 17):

a, 無法直接連接一個string和string_view,需要這樣:str+sv.data(); b, string_view可以作為參數按值傳遞給函數,因為其本質是指針和長度,非常高效 c, 無法從string_view隱式構建一個string,要么使用一個顯示的string構造函數,要么使用string_view::data(); d, auto sv = "my string_view"sv; // string_view字面量

不錯的string介紹:

https://www.cnblogs.com/ranbom/p/12675229.html

 

vector 轉換成 string

edit
play_arrow

brightness_4
// C++ program transform a vector into 
// a string. 
#include <vector> 
#include <string> 
#include <algorithm> 
#include <sstream> 
#include <iterator> 
#include <iostream> 
  
int main() 
{ 
  std::vector<int> vec; 
  vec.push_back(1); 
  vec.push_back(2); 
  vec.push_back(3); 
  vec.push_back(4); 
  vec.push_back(5); 
  vec.push_back(6); 
  
  std::ostringstream vts; 
  
  if (!vec.empty()) 
  { 
    // Convert all but the last element to avoid a trailing "," 
    std::copy(vec.begin(), vec.end()-1, 
        std::ostream_iterator<int>(vts, ", ")); 
  
    // Now add the last element with no delimiter 
    vts << vec.back(); 
  } 
  
  std::cout << vts.str() << std::endl; 
} 

https://www.geeksforgeeks.org/transform-vector-string/

 

c++ string 分配內存重載。可以查看創建string時內存分配情況

// sso.cpp

#include <iostream>
#include <string>

void* operator new(std::size_t count){
    std::cout << "   " << count << " bytes" << std::endl;
    return malloc(count);
}

void getString(const std::string& str){}

int main() {

    std::cout << std::endl;

    std::cout << "std::string" << std::endl;

    std::string small = "0123456789";
    std::string substr = small.substr(5);
    std::cout << "   " << substr << std::endl;

    std::cout << std::endl;

    std::cout << "getString" << std::endl;

    getString(small);
    getString("0123456789");
    const char message []= "0123456789";
    getString(message);

    std::cout << std::endl;

}

 

對大文件substr性能測試:

// substr.cpp

#include <chrono>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <vector>

#include <string_view>

static const int count = 30;
static const int access = 10000000;

int main(){

    std::cout << std::endl;

    std::ifstream inFile("grimm.txt");

    std::stringstream strStream;
    strStream <<  inFile.rdbuf();
    std::string grimmsTales = strStream.str();

    size_t size = grimmsTales.size();

    std::cout << "Grimms' Fairy Tales size: " << size << std::endl;
    std::cout << std::endl;

    // random values
    std::random_device seed;
    std::mt19937 engine(seed());
    std::uniform_int_distribution<> uniformDist(0, size - count - 2);
    std::vector<int> randValues;
    for (auto i = 0; i <  access; ++i) randValues.push_back(uniformDist(engine));

    auto start = std::chrono::steady_clock::now();
    for (auto i = 0; i  < access; ++i ) {
        grimmsTales.substr(randValues[i], count);//放到vector中時參考下面的性能測試,也許不會性能那么差。
    }
    std::chrono::duration<double> durString= std::chrono::steady_clock::now() - start;
    std::cout << "std::string::substr:      " << durString.count() << " seconds" << std::endl;

    std::string_view grimmsTalesView{grimmsTales.c_str(), size};
    start = std::chrono::steady_clock::now();
    for (auto i = 0; i  < access; ++i ) {
        grimmsTalesView.substr(randValues[i], count);
    }
    std::chrono::duration<double> durStringView= std::chrono::steady_clock::now() - start;
    std::cout << "std::string_view::substr: " << durStringView.count() << " seconds" << std::endl;

    std::cout << std::endl;

    std::cout << "durString.count()/durStringView.count(): " << durString.count()/durStringView.count() << std::endl;

    std::cout << std::endl;

}

 

參考:https://www.modernescpp.com/index.php/c-17-avoid-copying-with-std-string-view

 

 

性能測試

來自網址:https://quick-bench.com/q/I53xUH8inBWFyLCbZPu3y5jlEyU

用c++ 17的string_view替換實現做測試。

string 在沒有優化時慢。單在 o3 優化后,反而更快。 

#include <string_view>
#include <algorithm>

std::vector<std::string>
split(const std::string& str, const std::string& delims = " ")
{
    std::vector<std::string> output;
    auto first = std::cbegin(str);

    while (first != std::cend(str))
    {
        const auto second = std::find_first_of(first, std::cend(str),
            std::cbegin(delims), std::cend(delims));
        
        if (first != second)
            output.emplace_back(first, second); //注意這么沒有用substr。性能不會下降???? if (second == std::cend(str))
            break;

        first = std::next(second);
    }

    return output;
}

std::vector<std::string_view>
splitSV(std::string_view strv, std::string_view delims = " ")
{
    std::vector<std::string_view> output;
    size_t first = 0;

    while (first < strv.size())
    {
        const auto second = strv.find_first_of(delims, first);
        
        if (first != second)
            output.emplace_back(strv.substr(first, second-first));

        if (second == std::string_view::npos)
            break;

        first = second + 1;
    }

    return output;
}

const std::string_view LoremIpsumStrv{ "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididuntsuperlongwordsuper ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
"quis nostrud exercitation ullamco laboris nisi ut aliquipsuperlongword ex ea commodo consequat. Duis aute"
"irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
"Excepteur sint occaecat cupidatatsuperlongword non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." };


static void StringSplit(benchmark::State& state) {
  std::string str { LoremIpsumStrv };
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    auto v = split(str);
    benchmark::DoNotOptimize(v);
  }
}
// Register the function as a benchmark
BENCHMARK(StringSplit);

static void StringViewSplit(benchmark::State& state) {
  for (auto _ : state) {
    auto v = splitSV(LoremIpsumStrv);
    benchmark::DoNotOptimize(v);
  }
}
BENCHMARK(StringViewSplit);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM