C++ 复制常量字符*

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2287731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:53:59  来源:igfitidea点击:

Copy const char*

c++stringchar

提问by Ilya Suzdalnitski

I'm receiving a c-string as a parameter from a function, but the argument I receive is going to be destroyed later. So I want to make a copy of it.

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

Here's what I mean:

这就是我的意思:

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
}

What I want to achieve is not simply assign one memory address to another but to copy contents. I want to have filename as "const char*" and not as "char*".

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

I tried to use strcpy but it requires the destination string to be non-const.

我尝试使用 strcpy 但它要求目标字符串是非常量的。

Is there a way around? Something without using const_cast on filename?

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

Thanks.

谢谢。

回答by Pontus Gagge

Use a std::stringto copy the value, since you are already using C++. If you need a const char*from that, use c_str().

使用 astd::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();
    }
}

回答by Tadeusz Kopec

I agree that the best thing (at least without knowing anything more about your problem) is to use std::string. But if you insist on managing memory by yourself, you have to manage it completely. So the C++ way:

我同意最好的方法(至少在不了解您的问题的情况下)是使用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] = '
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?
}
'; // I'm paranoid, maybe someone has changed something in _filename :-) delete[] filename; filename = tmp_filename; }

and the C way

和 C 方式

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

回答by Cthutu

There's a function in the Standard C library (if you want to go the C route) called _strdup. It uses malloc to do the actual allocation so you will need to call free when you're done with the string.

标准 C 库中有一个名为 _strdup 的函数(如果你想走 C 路线)。它使用 malloc 进行实际分配,因此您在处理完字符串后需要调用 free。

So for example,

例如,

const char *filename;

Of course, don't forget to free the filename in your destructor.

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

回答by Patrick

You have to decide whether you want your file name to be const (so it cannot be changed) or non-const (so it can be changed in MyClass::func).

你必须决定你的文件名是const(所以它不能改变)还是non-const(所以它可以在MyClass::func中改变)。

回答by mlvljr

[Assuming you continue implementing your class' internals in the C-style, which may or may not be beneficial in terms of development and execution speed (depending on the whole project's design) but is generally not recommended in favor of std::stringand friends.]

[假设您继续以 C 风格实现类的内部结构,这在开发和执行速度方面可能有益也可能无益(取决于整个项目的设计),但通常不推荐给std::string朋友们使用。]

Turning

车削

char *filename;

into

进入

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

will not make you happy with the strcpy, since you actually need some memory for a copy of your string :)

不会让您满意strcpy,因为您实际上需要一些内存来保存字符串的副本:)

For the manual memory management code part, please see Tadeusz Kopec's answer, which seems to have it all right.

手动内存管理代码部分,请看Tadeusz Kopec的回答,貌似没问题。

Also, keep in mind that there is a difference between

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

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

and

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

In the first case, you can make filenamepoint to any other const charstring, in the second, you can only change that string "in-place" (so keeping the filenamevalue the same, as it points to the same memory location). Of course one can combine these two (or none of them) if needed.

在第一种情况下,您可以filename指向任何其他const char字符串,在第二种情况下,您只能“就地”更改该字符串(因此保持filename值相同,因为它指向相同的内存位置)。当然,如果需要,可以将这两者结合起来(或两者都不结合)。

P.S. If you name your member function's parameter _filenameonly to avoid naming collision with the member variable filename, you can just prefix it with this(and get rid of the underscore):

PS如果你命名你的成员函数的参数_filename只是为了避免与成员变量的命名冲突filename,你可以在它前面加上前缀this(并去掉下划线):

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

回答by Andy Shellam

If you want to stick to plain C, use strncpy. But I agree with Ilya, use std::string as it's already C++. If it's your application that's calling your method, you could even receive a std::string in the first place as the original argument is going to be destroyed.

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

回答by Narendra N

Why do you have it as const, If you need to change them in one of the methods of the class.

如果您需要在类的方法之一中更改它们,为什么要将其作为 const 使用。

Anyways, non-static const data members and reference data members cannot be assigned values; you should use initialization list with the constructor to initialize them.

无论如何,不​​能为非静态常量数据成员和引用数据成员赋值;您应该在构造函数中使用初始化列表来初始化它们。

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

An initializer can also call a function as below

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

##代码##

Didn't verify this particular case which is the apt one, but initialization list is the way to assign values to non static const data members.

没有验证这种特殊情况,这是最合适的情况,但初始化列表是将值分配给非静态常量数据成员的方法。

回答by Tronic

char const*implies that the class does not own the memory associated with it. The owner always needs a non-const pointer because otherwise the memory couldn't be freed. When you have non-const pointer, you can allocate the memory for it and then use strcpy(or memcpy) to copy the string itself. However, in your situation using std::stringinstead is a much better option.

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