【问题标题】:Value to std::string while keeping backwards compatibility对 std::string 的价值,同时保持向后兼容性
【发布时间】:2018-05-14 09:10:14
【问题描述】:

在保持向后兼容性的同时将值转换为 std::string 的简单实用函数。
可能是一个愚蠢的问题,但我很想听听一些关于它的意见,或者这样做是否有任何缺陷:

     template<typename T>
     std::string toString(T parm)
     {
#ifdef CXX11_AVAILABLE
         return std::to_string(parm);
#else
         std::ostringstream stream;
         stream << parm;

         return stream.str();
#endif
     }

如果我这样做,它会在内存中创建一个副本吗?
提前感谢您的回答:)

【问题讨论】:

  • 是的,直到 c++17 ostringstream::str() 返回底层字符串的副本。从 c++17 开始,str() 具有 r 值形式。
  • @RichardHodges 谢谢! DevSolar 谢谢你的参考,但老实说,我已经看过那篇文章,它对向后兼容性并不是很具体。您能否解释一下为什么 __cplusplus 定义会检查 C++11?
  • 您的模板接受各种 T 但 std::to_string() 将无法转换 char[]const char *std::ostringstream 将。
  • @RichardHodges:那不是 C++17;那是C++ 20。并且它将具有不同的功能,而不是 r 值重载。
  • @RichardHodges ostringstream::str() 是纯右值(任何按值返回的函数调用也是如此)。我猜你指的是一些未来的函数,它将把底层字符串移出 ostringstream; C++17 中没有这样的东西

标签: c++ c++11 tostring


【解决方案1】:

几点:

首先,您要检查if __cplusplus &gt; 201103L,而不是#ifdef CXX11_AVAILABLE;有关解释,请参阅:

http://stackoverflow.com/questions/11053960/ddg#11054055

现在,无论您使用的是哪个 C++ 版本,您都将至少拥有一份副本,只需将字符串传送到 ostringstream 即可。

此外,您将通过每个该死的呼叫toString() 创建和销毁ostringstream - 这太糟糕了! ...至少这样做:

namespace detail {
inline std::ostringstream& get_ostringstream(){
        static thread_local std::ostringstream stream;
        stream.str("");
        stream.clear();
        return stream;
}
} // namespace detail

然后在toString(),替换

std::ostringstream oss;

std::ostringstream& oss = detail::get_ostringstream();

最后,请记住最终副本 - oss.str() 受制于 Return Value Optimization (RVO),这在 C++17 中是强制性的,并且大多数编译器都应用了早期标准。因此,如果您使用函数的结果初始化一个字符串,oss.str() 副本的构造将在该外部字符串的地址处进行。

编辑:实际上,如果这是对性能至关重要的代码,那么您不应该使用通用字符串转换函数,并且可能根本不使用std::string。当然——在定制任何东西之前,先分析一下你在哪里损害了性能。

【讨论】:

  • 感谢您的澄清!这就是我一直在寻找的答案:) P.S:我忘了提到 CXX11_AVAILABLE 只是 __cplusplus > 201103L 的定义。
猜你喜欢
  • 1970-01-01
  • 2014-06-04
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
相关资源
最近更新 更多