首页 文章

复制const char *

提问于
浏览
12

我从函数接收一个c字符串作为参数,但我收到的参数将在以后销毁 . 所以我想复制一份 .

这就是我的意思:

class MyClass
{
private:
 const char *filename;

public:
 void func (const char *_filename);
}

void MyClass::func (const char *_filename)
{
 filename = _filename; //This isn't going to work
}

我想要实现的不是简单地将一个内存地址分配给另一个,而是复制内容 . 我希望文件名为“const char *”而不是“char *” .

我试图使用strcpy,但它要求目标字符串是非const .

有办法吗?没有在文件名上使用const_cast的东西?

谢谢 .

8 回答

  • 1

    使用 std::string 复制值,因为您已经在使用C . 如果你需要 const char* ,请使用 c_str() .

    class MyClass
    {
    private:
        std::string filename;
    public:
        void setFilename(const char *source)
        {
            filename = std::string(source);
        }
    
        const char *getRawFileName() const
        {
            return filename.c_str();
        }
    }
    
  • 7

    我同意最好的事情(至少在不了解你的问题的情况下)是使用 std::string . 但如果你坚持自己管理内存,你必须完全管理它 . 所以C方式:

    class MyClass
    {
    private:
     const char *filename;
    
     MyClass(const MyClass&); // no implementation
     MyClass operator=(const MyClass &); // no implementation
    
    public:
     MyClass() {filename = 0;}
     ~MyClass() {delete[] filename;}
    
     void func (const char *_filename);
    }
    
    void MyClass::func (const char *_filename)
    {
     const size_t len = strlen(_filename);
     char * tmp_filename = new char[len + 1];
     strncpy(tmp_filename, _filename, len);
     tmp_filename[len] = '\0'; // I'm paranoid, maybe someone has changed something in _filename :-)
     delete[] filename;
     filename = tmp_filename;
    }
    

    和C方式

    class MyClass
    {
    private:
     const char *filename;
    
     MyClass(const MyClass&); // no implementation
     MyClass operator=(const MyClass &); // no implementation
    
    public:
     MyClass() {filename = 0;}
     ~MyClass() {free(filename);}
    
     void func (const char *_filename);
    }
    
    void MyClass::func (const char *_filename)
    {
     free(filename);
     filename = strdup(_filename); // easier than C++, isn't it?
    }
    
  • 25

    您必须决定是否希望您的文件名是const(因此无法更改)或非const(因此可以在MyClass :: func中更改) .

  • 0

    标准C库中有一个函数(如果你想进入C路由),名为_strdup . 它使用malloc进行实际分配,因此当你完成字符串时你需要自由调用 .

    例如,

    void MyClass::func (const char *_filename)
    {
        if (filename)
        {
            free(filename);
        }
        filename = _strdup(_filename);
    }
    

    当然,不要忘记在析构函数中释放文件名 .

  • 2

    [假设你继续以C风格实现你的类'内部,这在开发和执行速度方面可能有利或可能没有好处(取决于整个项目的设计),但通常不建议支持 std::string 和朋友 .

    车削

    const char *filename;
    

    char *filename;
    

    不会让你对 strcpy 满意,因为你实际上需要一些内存来复制你的字符串:)

    对于手动内存管理代码部分,请参阅Tadeusz Kopec的答案,它似乎没有问题 .

    另外,请记住,两者之间存在差异

    const char *filename; // "filename" points to "const char" 
                          //  and is not const itself
    char const *filename; // semantically the same as above
    

    char * const filename; // "filename" is const and points to "char", 
                           //  which is not const
    

    在第一种情况下,您可以使 filename 指向任何其他 const char 字符串,在第二种情况下,您只能更改该字符串"in-place"(因此保持 filename 值相同,因为它指向相同的内存位置) . 当然,如果需要,可以将这两个(或者没有一个)组合在一起 .

    附:如果仅为成员函数的参数 _filename 命名以避免命名与成员变量 filename 的冲突,则可以在其前面添加 this (并删除下划线):

    void MyClass::func (const char *filename)
    {
     ...
     this.filename = copy;
    }
    
  • -1

    如果你想坚持使用普通的C,请使用strncpy . 但我同意Ilya,使用std :: string,因为它已经是C了 . 如果你的应用程序正在调用你的方法,你甚至可以首先收到一个std :: string,因为原始参数将被销毁 .

  • 0

    为什么你把它作为const,如果你需要在类的一个方法中更改它们 .

    无论如何,非静态const数据成员和参考数据成员不能被赋值;你应该使用初始化列表和构造函数来初始化它们 .

    MyClass::MyClass(const char *_filename) : filename( _filename ) 
    { 
       // filename = _filename; This isn't going to work 
    }
    

    初始化程序也可以调用如下函数

    MyClass::MyClass(const char *_filename) : filename( getfilename() ) 
    { 
       // filename = _filename; This isn't going to work 
    }
    

    没有验证这个特殊情况,但初始化列表是为非静态const数据成员赋值的方法 .

  • 1

    char const* 意味着该类不拥有与之关联的内存 . 所有者总是需要一个非const指针,否则无法释放内存 . 当你有非const指针时,你可以为它分配内存,然后使用 strcpy (或 memcpy )来复制字符串本身 . 但是,在你的情况下使用 std::string 代替是一个更好的选择 .

相关问题