[英]How to store a const char* to a char*?
我有这个代码按预期工作:
#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 *
作为输入)而不使用strcpy
(为了代码的实用性和可读性,以及学习),怎么可能我做? 保持const
,这很好用:
const char* name;
name = GetName();
但我仍然有const
。
试图只使用char*
:
char* name;
name = GetName();
我invalid conversion from 'const char*' to 'char*'
。 这种转换的最佳习惯是什么?
这种转换的最佳习惯是在整个代码中使用std::string
。 由于您使用的框架将const char*
作为其输入,因此您始终可以在std::string
上传递c_str()
调用的结果:
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*
:
const char* name = GetName();
由于您使用的框架采用const char*
您也很好。
如果需要非const指针,则无法复制字符串。 您可以为您创建一个功能,但您仍然有责任释放您从中获得的副本:
char* copy(const char* orig) {
char *res = new char[strlen(orig)+1];
strcpy(res, orig);
return res;
}
...
char *name = copy(GetName());
...
delete[] name;
return "Test text";
返回指向只读字符串文字的指针。
如果您正在使用一个以char*
作为输入的const char*
,并且您有一个const 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;
};
然后对于函数void foo(char* c)
,可以调用foo(Adapter("Hello"/*or any const char* */));
和foo
可以随意嵌入匿名临时的char*
! 您甚至可以增强此类以将构造函数转换为char*
,在这种情况下,只会获取指针的浅表副本(并且析构函数不会删除内存)。
在C ++中,“删除const
”的典型方法是使用const_cast<>
:
char *name = const_cast<char*>(GetName());
当然,这是不受欢迎的,丑陋的和潜在的危险,因为GetName()
确实可以返回指向不应该更改的内容的指针,然后你去允许自己更改它。 在这种情况下,这是一个很难找到错误的好方法。
解决方法是使用std::string
作为临时保留区域; 这将意味着复制字符串,但这可能是性能可接受的:
std::string s(GetName());
char *name = s.c_str();
这当然只有在s
超出范围时不保留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()
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.