首页 > 解决方案 > 从 std::string 对象到 char* 的显式转换,而不使用任何 std::string 成员函数

问题描述

这个问题不是关于任何问题,而更多的是一个深入理解.内存布局的问题std::string

我做了一些实验,并意识到可以显式转换std::stringchar*成功检索存储在std::string对象中的“字符串”。问题是,当一个std::string对象的起始地址与std::string::c_str()方法返回的地址不同时,怎么可能呢?

最近,我遇到了这种从std::string对象到char*. 最初,我认为这种转换不适用于std::string,但我很惊讶地知道它有效。

int main()
{
    std::string TestString = "Testing";

    void * pPointerToStringObject = (void *)&TestString;
    char * pExplicitlyConvertedString = *((char **)pPointerToStringObject);

    printf("Pointer to the string object : %p\n", pPointerToStringObject);
    printf("Pointer returned by c_str()  : %p\n\n", TestString.c_str());

    printf("\"String\" retrieved by explicit conversion of string object : \"%s\"\n", pExplicitlyConvertedString);
}

输出 :

Pointer to the string object : 0x7ffd84d3f4a0
Pointer returned by c_str()  : 0x7ffd84d3f4b0

"String" retrieved by explicit conversion of string object : "Testing"

标签: c++string

解决方案


这是一个执行问题。假设您使用的是 libstdc++。然后,第一个成员std::string指向存储的字符串(字符数组)的指针。这就是你得到的。

由于 SSO 应用于您的短字符串,因此该指针指向对象本身内部的缓冲区std::string,位于其偏移量 16b0 - a0十六进制)。

例如,如果我们查看 libstdc++ 实现:

_Alloc_hider _M_dataplus;  // offset 0 - an address of object - pointer to data
size_type    _M_string_length;

enum { _S_local_capacity = 15 / sizeof(_CharT) };

union
{
  _CharT     _M_local_buf[_S_local_capacity + 1];  // offset 16 - short string stored here
  size_type  _M_allocated_capacity;
};

指针存储在哪里_Alloc_hider

pointer _M_p; // The actual data.

请注意,您的代码可能无法以这种(未定义)方式与所示的其他实现一起使用。例如,libc++ 使用另一种方法来应用 SSO。通常,正如其他人在评论中指出的那样,您的代码可能会导致未定义的行为。


推荐阅读