【问题标题】:Deleting char* after assigning it to a string variable将 char* 分配给字符串变量后删除
【发布时间】:2013-02-25 16:36:03
【问题描述】:

我已经执行了下面的代码,它运行良好。由于它是关于指针的,我只是想确定一下。虽然我确信将 char* 分配给 string 会生成一个副本,即使我删除 char*,string var 也会保留该值。

    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <iostream>

    int main()
    {
        std::string testStr = "whats up ...";
        int strlen = testStr.length();
        char* newCharP = new char[strlen+1];
        memset(newCharP,'\0',strlen+1);
        memcpy(newCharP,testStr.c_str(),strlen);


        std::cout << "  :11111111   :   " << newCharP << "\n";
        std::string newStr = newCharP ;

        std::cout << "  2222222 : " << newStr << "\n";
        delete[] newCharP;
        newCharP = NULL;

        std::cout << "  3333333 : " << newStr << "\n";
    }

我只是在我的公司项目中更改了一些代码,并且 char* 在 C++ 中的函数之间传递。 char* 指针已复制到字符串,但 char* 在函数末尾被删除。我找不到任何具体的原因。所以我只是删除 char*,只要它被复制到一个字符串中。这会有什么问题吗...?

P.S:我已经在 Codereview 中问过这个问题,但我得到了将其移至 SO 的建议。所以我已将其标记为关闭并在此处发布问题。

【问题讨论】:

    标签: c++ string pointers char


    【解决方案1】:

    不,因为std::string 复制了您的char* 的内容,因此您可以在不再需要它时随意删除它。

    【讨论】:

      【解决方案2】:

      没有问题,只要newChar指向一个以null结尾的字符串,并且本身不为null。

      std::string 具有允许从const char* 进行隐式构造的构造函数。它会复制由输入 const char * 表示的字符串,因此它在假设 char* 是一个空终止字符串的情况下工作,因为没有其他方法可以知道要复制多少个字符到字符串自己的数据中贮存。此外,标准实际上不允许使用NULL 指针。

      【讨论】:

        【解决方案3】:

        代码很好,如果你查看std::basic_string here 的构造函数,你将能够推断std::string 有两个有趣的构造函数:

        (4) string(char const*,
                   size_type count,
                   Allocator const& alloc = Allocator() );
        
        (5) string(char const* s,
                   Allocator const& alloc = Allocator() );
        

        两者都执行复制,第一个准确读取 count 字符,而第二个读取直到遇到 NUL 字符。


        话虽如此,我积极鼓励您不要在这里使用动态分配。如果您想使用临时缓冲区,请考虑改用std::vector

        #include <stdio.h>
        #include <string.h>
        #include <string>
        #include <iostream>
        
        int main()
        {
            std::string testStr = "whats up ...";
            unsigned strlen = testStr.length();
        
            std::vector<char> buffer(strlen+1);
        
            memset(&buffer[0],'\0',strlen+1);
            memcpy(&buffer[0], testStr.c_str(), strlen);
        
            std::cout << "  :11111111   :   " << &buffer[0] << "\n";
        
            std::string newStr(&buffer[0]);
        
            std::cout << "  2222222 : " << newStr << "\n";
        
            buffer.clear();
        
            std::cout << "  3333333 : " << newStr << "\n";
        }
        

        注意:vectorstring 都有范围构造函数,可以从一系列迭代器中构建它们,我故意避免使用这些迭代器,以避免混淆和你不知所措。只需知道您可以使用它们来避免调用 memcpy 并冒着缓冲区溢出的风险。

        【讨论】:

        • 谢谢马特,实际上 char* 是从另一个函数传递的。就像我说的那样,我正在处理一些旧代码,我无法继续更改所有函数调用中的参数。我们的代码库非常大。并且这些 char* 的删除在函数的许多部分中执行,在某些条件下,每个部分只执行一次。虽然我不喜欢代码重复,所以我只是将 char* 复制到字符串并在函数本身的开头删除了 char*。
        • @ManikandarajS:哼!我知道你的痛苦,我不得不自己处理一些令人沮丧的应用程序:(在这种情况下,你正朝着正确的方向前进,试图限制“感染”并调整你必须处理的代码,让它变得更好!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-05
        • 2011-09-23
        • 1970-01-01
        • 2019-02-08
        • 1970-01-01
        • 2015-06-25
        • 1970-01-01
        相关资源
        最近更新 更多