我很想知道字符串类如何实现从字符数组复制以初始化其内容。
我的猜测是这样的:
1:找到字符数组的长度,N。(这是怎么做的?粗略的方法是分别查看每个字符,直到找到空字符?是否使用了更好的方法?)
2:分配N个字节的存储空间。
3:使用strcpy逐字节复制每个元素。
显然这不是一个非常复杂的问题,我只是想知道以下内容是否(基本上或大致相同):
std::string program_name(argv[0]);
和
std::string program_name;
int length = 0;
while(*(argv[0] + length) != '/0')
++ length;
++ length; // Depends on whether string contains the null character - usually I don't think it does?
program_name.resize(length); // Maybe use reserve instead?
std::cpy(program_name.data(), argv[0], length - 1); // Don't copy the null character at the end
无论如何都是这样的。我没有尝试编译上面的伪代码,因为我对方法的概念感兴趣,而不是关于如何完成此操作的细节。
答案 0 :(得分:3)
简而言之,您的实施几乎就是它的工作方式。
忽略std::string
从std::basic_string
实现的事实,该std::string
被模板化以处理存储在字符串中的各种数据类型(特别是“宽字符”),来自char *的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);
}
构造函数可写成这样的东西:
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
}
当然,由于实际实现的继承和模板性质,实际实现将更加间接[可能具有“增长/分配”的特定功能]。
这是libcxx中的REAL实现:
__init
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());
}
执行此操作:
new
它将一些技巧存储在指针内[并使用相关的分配器分配,可能不是traits_type::assign(__p[__sz], value_type());
],并显式初始化结束标记[__init
,作为对<{1}}可能会出现与C样式字符串不同的参数,因此无法保证结束标记。
traits_type::length()
是strlen
template <>
struct _LIBCPP_TYPE_VIS_ONLY char_traits<char>
{
...
static inline size_t length(const char_type* __s) {return strlen(__s);}
....
};
当然,其他STL实现可能会使用不同的详细实现,但大致上它只是我的简化示例,但是为了应对许多类型和重用代码而更加混淆。