In short, your implementation is pretty much how it works.
Ignoring the fact that std::string is implemented from std::basic_string which is templated to cope with various data types stored in the string (notably "wide characters"), std::string constructor from char * could be written something like this:
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);
}
Of course, the actual implementation will be more indirect [probably has a specific function to "grow/allocate", for example], due to the inheritance and templated nature of the real implementation.
Here's a REAL implementation out of libcxx:
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
}
where __init does this:
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());
}
It does some tricks to store the value inside the pointer [and allocate with the relevant allocator, which may not be new], and explicitly initializes the end marker [traits_type::assign(__p[__sz], value_type());, as the call to __init may happen with a different argument than a C style string, so end marker is not guaranteed.
traits_type::length() is strlen
template <>
struct _LIBCPP_TYPE_VIS_ONLY char_traits<char>
{
...
static inline size_t length(const char_type* __s) {return strlen(__s);}
....
};
Of course, other STL implementations may well use a different detail implementation, but roughly it is as my simplified example, but a bit more obfuscated to cope with many types and reusing code.
std::stringis available in the headers that come with your C++ compiler. Use the source, Luke. Spoiler alert: it's pretty much the way you envision, there's really nothing clever going on.strlenand the resizing needlessly initializes the buffer just to immediately overwrite it again.std::basic_stringstores a zero-terminator: Sincec_str()is required to return in O(1), storing a zero-terminator is pretty much mandatory.