c++:结构数组赋值中 const char* 的意外结果

问题描述 投票:0回答:2

c++:结构数组赋值中 const char* 的意外结果

我的代码:

#include <pthread.h>
#include <iostream>
#include <vector>

using namespace std;

typedef struct {
    int id;
    const char* name;
    const char* out;
} thread_info;

int main(int argc, char const *argv[])
{
    int err = 0;
    std::vector<thread_info> info_vec;
    info_vec.resize(10);

    for(int i = 0; i < 10; i++) {
        //info_vec[i].id = i;
        info_vec[i].name = to_string(i).c_str();
    }
    
    int count = 10;
    for (size_t i = 0; i < count; i++)
    {
        /* code */
        //cout << info_vec[i].id << endl;
        cout << info_vec[i].name << endl;
        

    }
}

结果是:

9
9
9
9
9
9
9
9
9
9

要求解释为什么结果不是“1 2 3 4 5 6 7 8 9” 我的代码有什么问题?

要求解释为什么结果不是“1 2 3 4 5 6 7 8 9” 我的代码有什么问题?

ps:如果我用id代替name,它可以打印“1 2 3 4 5 6 7 8 9”

c++ arrays struct char
2个回答
5
投票

to_string(i)
是临时的,因此内容在info_vec[i].name = to_string(i).c_str();之后被释放(或
其生命周期已结束
),即指针是悬挂

理论上,解引用释放的指针是UB,即任何事情都可能发生。实际上,正如你的编译器选择做的那样(这不是可移植的[^1]),它们都是

9
,因为它们都指向同一个地方;这是因为每个字符串都被分配,然后释放,下一个字符串在同一位置分配,等等。最终的字符串是
9
,因此你在这里得到
9
。然而,由于最终的字符串也被释放,如果其他内容占用了这块内存,
9
也会被覆盖。

您需要做的是制作例如

name
std::string
而不是
const char*
,它将保存内容,因为您将其复制到另一个地方。

[^1]:正如@Chris所说,既然是UB,看起来指向同一个地方的悬空指针可能会得到不同的内容。


0
投票
虽然

o_oTurtle 的答案是正确的,但核心信息必须是内存必须超出循环迭代的范围,以避免未定义的行为。这并不要求结构成员是 std::string

for(int i = 0; i < 10; i++) { string s = to_string(i).c_str(); info_vec[i].name = new char[s.size() + 1]; std::size_t len = s.copy(info_vect[i].name, 0, s.size()); info_vect[i].name[len] = '\0'; }
另请注意,在 C++ 中,您不需要 typedef。

struct thread_info { int id; const char* name; const char* out; };
如果您的结构将包含指向动态分配内存的原始指针,您可能需要定义一个析构函数(以及可能的构造函数、赋值运算符等)

© www.soinside.com 2019 - 2024. All rights reserved.