C++ std::string(char*char\u数组)是如何实现的?

C++ std::string(char*char\u数组)是如何实现的?,c++,arrays,string,char,C++,Arrays,String,Char,我想知道string类如何实现从字符数组复制以初始化其内容 我猜大概是这样的: 1:查找字符数组的长度,N。(这是如何做到的?一种粗略的方法是逐个查看每个字符,直到找到空字符为止?是否使用了更好的方法?) 2:分配N字节的存储空间 3:使用strcpy逐字节复制每个元素 显然,这不是一个非常复杂的问题,我只是想知道以下各项是否(基本上或近似地)等效: std::string program_name(argv[0]); 及 反正是这样的。我没有尝试编译上面的伪代码,因为我感兴趣的是方法的概念,

我想知道string类如何实现从字符数组复制以初始化其内容

我猜大概是这样的:

1:查找字符数组的长度,N。(这是如何做到的?一种粗略的方法是逐个查看每个字符,直到找到空字符为止?是否使用了更好的方法?)

2:分配N字节的存储空间

3:使用strcpy逐字节复制每个元素

显然,这不是一个非常复杂的问题,我只是想知道以下各项是否(基本上或近似地)等效:

std::string program_name(argv[0]);


反正是这样的。我没有尝试编译上面的伪代码,因为我感兴趣的是方法的概念,而不是这个操作如何完成的细节。

简而言之,您的实现在很大程度上取决于它的工作原理

忽略以下事实:
std::string
是从
std::basic_string
实现的,该字符串模板化以处理存储在字符串中的各种数据类型(特别是“宽字符”),
std::string
构造函数可以编写如下内容:

std::string(const char* init_value)
{
    size_t m_len = strlen(init_value);
    char *m_storage = new char[m_len+1];
    std::copy(m_storage, init_value, m_len+1);
}
当然,由于实际实现的继承性和模板化性质,实际实现将更加间接[例如,可能具有“增长/分配”的特定功能]

下面是一个真正的实现:

它使用一些技巧将值存储在指针内[并使用相关的分配器进行分配,该分配器可能不是
new
],并显式初始化结束标记[
traits\u type::assign(\uu p[\uu sz],value\u type());
,因为对
\uu init
的调用可能使用与C样式字符串不同的参数,所以不能保证使用结束标记

traits\u type::length()
strlen

template <>
struct _LIBCPP_TYPE_VIS_ONLY char_traits<char>
{
...
    static inline size_t length(const char_type* __s) {return strlen(__s);}
....
};
模板
结构LIBCPP类型仅显示字符特征
{
...
静态内联大小\u t长度(常量字符类型*\u s){返回strlen(\u s)}
....
};

<>当然,其他的STL实现可能使用不同的细节实现,但大致上它是我的简化示例,但是对于处理许多类型和重用代码有点模糊。

在C++编译器中使用的标题中可以使用<代码> STD::String 。请使用源代码卢克。这和你想象的差不多,真的没有什么聪明的地方。你的步骤在语义上是等价的,但效率不如优化的标准库实现。你的手动循环将比strlen慢得多,调整大小不需要初始化缓冲区,只是为了立即再次覆盖它。Exp根据Igor的评论,没有什么聪明的事情发生。c样式字符串被定义为以NUL字符结尾的连续字符数组。它不保留专用的长度字段。要回答您关于
std::basic_string
是否存储零终止符的问题:因为
c_str()
必须在O(1)中返回,存储零终止符几乎是强制性的。您的解决方案在概念上类似,但错误:“修改通过数据访问的字符数组是未定义的行为。”
std::string
不是从
std::basic_string
派生出来的;它是
std::basic_string
@T.C.的别名:重新编写以反映“混淆”是有点必要的:例如,任何非公共的东西都不能使用您可以合法定义的名称,并且类必须使用分配器和traits。您提供的代码似乎也在使用短字符串优化。@JamesKanze:当然,它是因为一个合理的原因而被混淆的,但它仍然比wh更复杂至少,如果你只是在家里和一个目标用户一起做一个爱好项目,你会这样写…;)@matstpeterson,甚至是我大部分时间都会做的专业工作:-)。
template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s)
{
    _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr");
    __init(__s, traits_type::length(__s));
#if _LIBCPP_DEBUG_LEVEL >= 2
    __get_db()->__insert_c(this);
#endif
}
template <class _CharT, class _Traits, class _Allocator>
void
basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
{
    if (__sz > max_size())
        this->__throw_length_error();
    pointer __p;
    if (__sz < __min_cap)
    {
        __set_short_size(__sz);
        __p = __get_short_pointer();
    }
    else
    {
        size_type __cap = __recommend(__sz);
        __p = __alloc_traits::allocate(__alloc(), __cap+1);
        __set_long_pointer(__p);
        __set_long_cap(__cap+1);
        __set_long_size(__sz);
    }
    traits_type::copy(_VSTD::__to_raw_pointer(__p), __s, __sz);
    traits_type::assign(__p[__sz], value_type());
}
template <>
struct _LIBCPP_TYPE_VIS_ONLY char_traits<char>
{
...
    static inline size_t length(const char_type* __s) {return strlen(__s);}
....
};