簡體   English   中英

從 `const char *` 隱式構造 `const std::string` 有效嗎?

[英]Is implicit construction of `const std::string` from `const char *` efficient?

像許多人一樣,我習慣將新的字符串函數編寫為const std::string &的函數。 優點是效率(您可以傳遞現有的std::string對象而不會產生復制/移動的開銷)和靈活性/可讀性(如果您只有一個const char *您可以傳遞它並隱式完成構造,而不會造成混亂使用顯式的std::string構造來構建您的代碼):

#include <string>
#include <iostream>
unsigned int LengthOfStringlikeObject(const std::string & s)
{
    return s.length();
}
int main(int argc, const char * argv[])
{
    unsigned int n = LengthOfStringlikeObject(argv[0]);
    std::cout << "'" << argv[0] << "' has " << n << " characters\n";
}

我的目標是編寫能夠有效處理長字符串的高效跨平台代碼。 我的問題是,在隱式構造過程中會發生什么? 是否有任何保證不會復制字符串? 讓我感到震驚的是,因為一切都是const ,所以不需要復制——只需要一個圍繞現有指針的薄 STL 包裝器就足夠了——但我不確定我應該期望這種行為如何依賴於編譯器和平台。 始終顯式編寫 function 的兩個版本是否更安全,一個用於const std::string &一個用於const char *

如果您將const char*傳遞給接受std::string的東西,無論是否引用,都會構造一個字符串。 如果您將其發送給引用並警告存在隱式臨時 object,編譯器甚至可能會抱怨。

現在這可能會被編譯器優化,並且一些實現不會為小字符串分配 memory。 編譯器還可能在內部對其進行優化以使用 C++17 string_view 它本質上取決於您將對代碼中的字符串做什么。 如果你只使用常量成員函數,一個聰明的編譯器可能會優化出來。

但這取決於實施,不在您的控制范圍內。 如果要接管,可以顯式使用std::string_view

讓我印象深刻的是,因為一切都是 const,所以不需要復制——只需要一個圍繞現有指針的薄 STL 包裝器即可

我不認為這個假設是正確的。 僅僅因為你有一個指向 const 的指針,並不意味着基礎值不能改變。 它僅意味着無法通過該指針更改該值。 指針可能指向可以隨時更改的非常量存儲。

因此,庫必須制作自己的副本(以提供“正確的”字符串可觀察行為)。 對 libstdc++ 的快速回顧表明它總是制作副本。 char*的構造不是內聯的,因此如果沒有 static 鏈接和 LTO,就無法對其進行優化。

雖然極其微不足道的靜態鏈接程序可能會使用 LTO 優化副本(我無法重現這一點),但我認為通常不太可能執行這種優化(特別是考慮到char*的別名規則)。 g++ 甚至不對字符串文字執行此優化。

如果您不想復制,那么string_view就是您想要的。

然而,這個好處也帶來了問題。 具體來說,您必須確保您傳遞的存儲持續“足夠長”。

對於字符串文字,這沒問題。 對於argv[0] ,這幾乎肯定不是問題。 對於任意字符序列,您需要考慮它們。

但你可以寫:

unsigned int LengthOfStringlikeObject(std::string_view sv)
{
    return sv.length();
}

並用stringconst char *調用它,就可以了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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