C++ 如何将常量字符*存储到字符*?
我有一个工作如预期:C++ 如何将常量字符*存储到字符*?,c++,char,constants,type-conversion,C++,Char,Constants,Type Conversion,我有一个工作如预期: #define MAX_PARAM_NAME_LEN 32 const char* GetName() { return "Test text"; } int main() { char name[MAX_PARAM_NAME_LEN]; strcpy(name, GetName()); cout << "result: " << name << endl; } 但是我仍然有常量 尝试仅使用
#define MAX_PARAM_NAME_LEN 32
const char* GetName()
{
return "Test text";
}
int main()
{
char name[MAX_PARAM_NAME_LEN];
strcpy(name, GetName());
cout << "result: " << name << endl;
}
但是我仍然有常量
尝试仅使用char*
:
char* name;
name = GetName();
我得到了从“const char*”到“char*”的无效转换
。这种转换的最佳习惯是什么? < p> C++中,典型的“滴<代码> const ”是使用<代码> conconsCAST >:
当然,只有当s
超出范围时,没有保留name
时,这才有效。如果是这种情况,那么您将拥有某种形式的持久字符串存储层。返回“测试文本”返回指向只读字符串文本的指针
如果您使用的函数将char*
作为输入,并且您有一个const char*
(例如只读字符串文字),那么您应该向这些函数提供从该const char*
开始的字符串的深度副本
否则,如果函数试图修改只读字符串,则可能会在运行时出现未定义的行为
你现在拥有的是足够的;假设您不能使用std::string
。(如果您可以使用std::string
,并且所有框架函数都采用const char*
输入,那么我建议您重构代码以使用std::string
,并将该字符串类上的c_str()
方法的输出传递给框架函数。)
最后,如果您的一些框架函数需要一个char*
,那么您可以自己构建一个小的适配器类:
class Adapter
{
public:
Adapter(const& Adapter) = delete; /*don't try to copy me please*/
Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
Adapter(const char* s) : m_s(::strdup(s))
{
}
~Adapter() /*free memory on destruction*/
{
::free(m_s); /*use free to release strdup memory*/
}
operator char*() /*implicit cast to char* */
{
return m_s;
}
private:
char* m_s;
};
然后对于函数voidfoo(char*c)
,可以调用foo(Adapter(“Hello”/*或任意常量char**/)
和foo
可以使用嵌入在匿名临时文件中的char*
随心所欲!您甚至可以增强该类,将构造函数转换为char*
,在这种情况下,只获取指针的一个浅拷贝(析构函数不会删除内存)。这种转换的最佳习惯是在整个代码中使用std::string
。由于您正在使用的框架将const char*
作为其输入,因此您始终可以将调用结果传递给您的std::string
:
std::string GetName() {
return "Test text";
}
int main() {
std::string name = GetName();
int res = external_framework_function(name.c_str());
cout << "result: " << res << " for " << name << endl;
}
由于您使用的框架采用constchar*
,因此您在这里也很好
如果您需要一个非常量指针,则无法复制字符串。您可以创建一个函数来为您执行此操作,但您仍将负责释放从中获得的副本:
char* copy(const char* orig) {
char *res = new char[strlen(orig)+1];
strcpy(res, orig);
return res;
}
...
char *name = copy(GetName());
...
delete[] name;
您可以显式地强制转换它<代码>(char*)getName()
。但你可能不应该。因为const
位的意思类似于“承诺不改变它”。因此,如果我有一个函数void foo(const char*string)
我会说:“给我一个指向字符串的指针,我不会改变它。”
如果您声明一个变量const char*string=“hello”代码>您的意思是,此字符串不应更改。因为你做出了这个承诺,编译器知道,并且可以使你的代码更有效率。这就是为什么:
const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true
您的编译器知道您不会更改a
或b
,因此它使它们指向相同的地址,因此它只需存储一个“hello”
字符串。如果您现在开始更改a
,b
也会更改,这不是您想要的
长话短说,如果您完全确定您调用的函数不会更改字符串,那么您可以显式地强制转换它。(或者更好,将函数更改为(const char*)
(如果是您的)。
如果你不确定,你必须复印一份。(就像你已经在使用strcpy()
)。你想做什么?如果您不想更改字符串,第一个习惯用法为您服务,并且不使用额外的内存;如果您想更改字符串,您需要将其内容复制到其他位置(因此您需要strcpy或类似内容)。是否从const char*
未定义的行为中删除const?如果我可以问一下,为什么您要建议一些不受欢迎的内容,而不给出其他建议?@Default,因为这是海报想要知道的方法,我也不能确定在这种情况下会不会很糟糕。.c_str()
是常量<代码>字符*name=s.c_str()代码>不可编译。@默认删除常量不是UB。但是你是对的,std::string::c_str
将不起作用,因为它返回const char*
。如果我想将const char*
内容“复制”到char*
(因此,不指定固定大小),该怎么办?我不知道那个字符*的大小,因为稍后我会找到另一个字符。哦,等等。我知道我可以使用char*name
和thanstrcpy(name,GetName())代码>也是。基本上,我得到了一个长度不确定的字符串,它可以完成我的任务。这样做正确吗?@paizza No.使用类似于std::string name=GetName()的东西
然后将name.c_str()
传递给任何需要const char*
的框架函数。还可以创建字符串的副本。不过,稍后需要释放内存,所以在C++中使用<代码> STD::String 要容易得多。code>c_str
是一个函数。你为什么建议进行潜在危险的强制转换?从C++字符串文本中获得非const C字符串的唯一正确方法是复制它。任何修改非常量铸造版本的尝试都是无效的。请不要建议(几乎肯定)会导致难以诊断程序行为的方法。
std::string GetName() {
return "Test text";
}
int main() {
std::string name = GetName();
int res = external_framework_function(name.c_str());
cout << "result: " << res << " for " << name << endl;
}
const char* name = GetName();
char* copy(const char* orig) {
char *res = new char[strlen(orig)+1];
strcpy(res, orig);
return res;
}
...
char *name = copy(GetName());
...
delete[] name;
const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true