优化 C++ const std::string 文字声明以实现编译时初始化和运行时性能

问题描述 投票:0回答:1
我希望在庞大的

c++ 20 项目中优化 const 字符串文字的使用,以增强编译和运行时性能 在许多源文件中,字符串文字都是用 const std::string

 声明的,如下例所示(定义了数十个字符串文字,然后连接起来形成新的字符串文字):

之前

// Example namespace { const std::string kPluginApi("plugins-api"); const std::string kGlobal(".global"); const std::string kInternal(".internal"); } namespace { const std::string kGLobalApiPlugin = kPluginApi + kGlobal; const std::string kInternalApiPlugin = kPluginApi + kInternal; }
问题是 

std::string

 通常在运行时初始化,尽管有 const 限定符。

由于

std::string

 通常涉及动态内存分配,因此运行时初始化,我想到使用 
constexpr const char *
 来确保尽可能编译时初始化,如下所示:

之后

namespace { constexpr const char * kPluginApi = "plugins-api"; constexpr const char * kGlobal = ".global"; constexpr const char * kInternal = ".internal"; } namespace { const std::string kGLobalApiPlugin = std::string(kPluginApi) + kGlobal; const std::string kInternalApiPlugin = std::string(kPluginApi) + kInternal; }

    第二种方法真的比第一种方法更好吗?我主要关心
  • 运行时性能,因为串联首先涉及到std::string
    转换。
  • 有没有更好的方法?
c++ performance c++20 stdstring const-char
1个回答
0
投票
您可以像这样使用编译时串联:

#include <array> #include <string_view> namespace ce { template <typename input_iterator_t, typename output_iterator_t> constexpr void ce_copy(input_iterator_t first, input_iterator_t last, output_iterator_t to) { for(auto it = first; it != last; ++it, ++to) { *to = *it; } } template <std::size_t N> class string final { public: constexpr string() = default; constexpr string(const char (&str)[N]) noexcept { ce_copy(str, str + N, m_str.begin()); } constexpr string(const string&) = default; //explicit conversion to string_view constexpr std::string_view sv() const noexcept { return std::string_view{ c_str(), N - 1 }; } // implicit conversion to string_view constexpr operator std::string_view() const noexcept { return std::string_view{ c_str(), N - 1 }; } constexpr const char* c_str() const noexcept { return m_str.data(); } constexpr char* str() noexcept { return m_str.data(); } constexpr auto cbegin() const noexcept { return m_str.cbegin(); } constexpr auto cend() const noexcept { return m_str.cend(); } constexpr bool operator==(const char* rhs) const noexcept { return sv() == std::string_view{ rhs }; } template <std::size_t M> constexpr auto concat(const string<M>& rhs) const noexcept { string<N + M - 1> result; ce_copy(cbegin(), cend(), result.str()); ce_copy(rhs.cbegin(), rhs.cend(), result.str() + N - 1); return result; } constexpr auto operator[](const std::size_t index) const noexcept { return m_str[index]; } constexpr auto& operator[](const std::size_t index) noexcept { return m_str[index]; } private: std::array<char, N> m_str{}; }; } //namespace ce static constexpr ce::string kGlobal{ ".global" }; static constexpr ce::string kInternal(".internal"); static constexpr ce::string kPluginApi("plugins-api"); static constexpr ce::string kGLobalApiPlugin = kPluginApi.concat(kGlobal); static constexpr ce::string kLocalApiPlugin = kPluginApi.concat(kInternal); int main() { static_assert(kGLobalApiPlugin == "plugins-api.global"); }
    
© www.soinside.com 2019 - 2024. All rights reserved.