为char数组动态分配内存

时间:2018-10-01 18:12:54

标签: c++

下一段代码有一些理解上的问题。

#include<iostream>
using namespace std;
int main() {
    char *str = "hi";
    char *p = new char[strlen(str) + 1];
    for (int i = 0; *(str + i); i++)
        *(p + i) = *(str + i);
    cout << p << endl;
    return 0;
}

结果如下:

hi═¤¤¤¤

当我使用调试器时,我可以看到我的 p 指向一个由10或15或其他数量的符号组成的数组(取决于编译情况),所以我得到了更多“ hi”之后的符号。但是,当我使用strcpy()时:

#include<iostream>
using namespace std;
int main() {
    char *str = "hi";
    char *p = new char[strlen(str) + 1];
    strcpy(p, str);
    cout << p << endl;
    return 0;
}

我得到结果:

hi

所以,有人可以向我解释一下,为什么我在程序的第一个示例中得到了这样的结果,以及如何像在第二个示例中那样对它进行重新处理以得到结果。 预先感谢。

3 个答案:

答案 0 :(得分:2)

您没有将终止空字符添加到p

添加行

*(p + i) = '\0';

for循环之后。但是,为此,您必须在i循环之前声明for

int i = 0;
for (i = 0; *(str + i); i++)
    *(p + i) = *(str + i);
*(p + i) = '\0';
cout << p << endl;

答案 1 :(得分:2)

您忘记在第一个示例中以零终止字符串:

#include <cstddef>
#include <iostream>

int main()
{
    char const *str = "hi";
    std::size_t length = std::strlen(str);
    char *p = new char[length + 1];
    for (std::size_t i = 0; i < length; ++i)
        p[i] = str[i];
    str[length] = '\0';
    std::cout << p << '\n';
    delete[] p;
}

请注意:字符串文字是不可变的,因此应由char const*指向。用于保存内存中对象大小或索引大小的正确类型是std::size_t,而不是int。如果您执行手动内存管理,则必须确保通过将使用new获得的指针传递到delete并将指针从new[]传递到delete[]来释放分配的内存。

但是,您不应该手动进行内存管理。使用容器std::stringstd::vector,或至少使用智能指针,例如std::shared_ptr<>std::unique_ptr<>

答案 2 :(得分:2)

答案是在循环的停止条件下,即*(str + i)

for (int i = 0 ; *(str + i) ; i++)
    *(p + i) = *(str + i);

请注意,表达式中没有比较运算符。在需要逻辑条件的上下文中使用像这样的表达式时,存在与零的隐式比较,即*(str + i)*(str + i) != 0的含义相同。

现在应该清楚为什么字符串保持未终止:循环在发现空终止符时停止,并且不将其复制到目标字符串中。

做同一件事的一种稍微“神秘”的方法是将比较与赋值结合起来,就像K&R书那样:

for (int i = 0 ; *(p + i) = *(str + i) ; i++)
    ;

现在,在分配后进行null测试,以确保目的地为null终止。