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
Copy const char*
提问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::string
to 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::string
and 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 filename
point to any other const char
string, in the second, you can only change that string "in-place" (so keeping the filename
value 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 _filename
only 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::string
instead is a much better option.
char const*
意味着该类不拥有与其关联的内存。所有者总是需要一个非常量指针,否则无法释放内存。当您有非常量指针时,您可以为其分配内存,然后使用strcpy
(或memcpy
) 复制字符串本身。但是,在您的情况下,使用std::string
代替是更好的选择。