C++ 17 std::string_view使用介紹

C++中與字符串有兩種風格,分別是C風格的字符串、std::string字符串。C風格的字符串性能更高,但是也不方便操作使用。如下示例:

#include <iostream>
#include <string>

int main()
{
	//C風格字符串總是以null結尾
	char cstr1[] = { 'y', 'a', 'n', 'g', NULL};	
	char cstr2[5];
	strcpy(cstr1, cstr2);
	std::cout << cstr2 << std::endl;

	//C++風格的字符串操作更方便,但是性能不如C風格字符串
	std::string str = "yang";
	std::string str2 = str;
}

C++17中我們可以使用std::string_view來獲取一個字符串的視圖,字符串視圖並不真正的創建或者拷貝字符串,而只是擁有一個字符串的查看功能。std::string_view比std::string的性能要高很多,因爲每個std::string都獨自擁有一份字符串的拷貝,而std::string_view只是記錄了自己對應的字符串的指針和偏移位置。當我們在只是查看字符串的函數中可以直接使用std::string_view來代替std::string。

#include <iostream>
#include <string>
#include <string_view>

int main()
{

	const char* cstr = "yangxunwu";
	std::string_view stringView1(cstr);
	std::string_view stringView2(cstr, 4);
	std::cout << "stringView1: " << stringView1 << ", stringView2: " << stringView2 << std::endl;

	std::string str = "yangxunwu";
	std::string_view stringView3(str.c_str());
	std::string_view stringView4(str.c_str(), 4);
	std::cout << "stringView3: " << stringView1 << ", stringView4: " << stringView2 << std::endl;
}

輸出

 

 

你可以把原始的字符串當作一條馬路,而我們是在馬路邊的一個房子裏,我們只能通過房間的窗戶來觀察外面的馬路。這個房子就是std::string_view,你只能看到馬路上的車和行人,但是你無法去修改他們,可以理解你對這個馬路是隻讀的。正是這樣std::string_view比std::string會快上很多。

#include <iostream>
#include <string>
#include <chrono>
#include <string_view>

//計時器
class Timer
{
private:
	std::string title;
	std::chrono::high_resolution_clock::time_point m_start, m_stop;
public:
	Timer(const std::string& title): title(title)
	{
		m_start = std::chrono::high_resolution_clock::now();
	}

	~Timer()
	{
		stop();
	}

	void stop()
	{
		m_stop = std::chrono::high_resolution_clock::now();
		std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(m_stop - m_start);
		std::cout << title << " " << (ms.count()) * 0.001 << "s\n";
	}
};

void FunctionWithString(const std::string& string)
{
}

void FunctionWithString(const std::string_view& stringView)
{
}

int main()
{

	{
		Timer timer("std::string");
		for (int i = 0; i < 1000000; i++)
		{
			std::string name = "Yang Xunwu";
			std::string firstName = name.substr(0, 4);
			std::string lastName = name.substr(4, 9);
			FunctionWithString(firstName);
			FunctionWithString(lastName);
		}
	}

	{
		Timer timer("std::string_view");
		for (int i = 0; i < 1000000; i++)
		{
			const char* name = "Yang Xunwu";
			std::string_view firstName = std::string_view(name, 4);
			std::string_view lastName = std::string_view(name + 4, 9);
			FunctionWithString(firstName);
			FunctionWithString(lastName);
		}
	}
}

輸出

之所以這樣時因爲std::string在進行操作時會重新分配內存,生成一個對應的std::string副本,大量的new操作。而std::string_view操作,從頭到尾其實只有一個字符串數據,其它皆爲視圖。這也是需要注意的地方,因爲std::string_view是原始字符串的視圖,如果在查看std::string_view的同時修改了字符串,或者字符串被消毀,那麼將是未定義的行爲。

#include <iostream>
#include <string>
#include <string_view>

std::string_view GetStringView()
{
	std::string name = "xunwu";

	return std::string_view(name);	//離開作用域時,name已經被回收銷燬
}

int main()
{
	std::string_view stringView = GetStringView();
	std::cout << stringView << std::endl;
}

  輸出:

 

 是不是很燙呢。。。

 

參考:https://www.learncpp.com/cpp-tutorial/6-6a-an-introduction-to-stdstring_view/

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章