简体   繁体   English

如何将const char *存储到char *?

[英]How to store a const char* to a char*?

I have this code that works as expected: 我有这个代码按预期工作:

#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;
}

If I'd like to store the result to a char * (because some functions within a Frameworks I'm using use only char * as input) without using the strcpy (for practicality and readability of code, and learning too), how could I do? 如果我想将结果存储到char * (因为我正在使用的框架中的某些函数仅使用char *作为输入)而不使用strcpy (为了代码的实用性和可读性,以及学习),怎么可能我做? Keeping in const , this works well: 保持const ,这很好用:

const char* name;
name = GetName();

but I still have const . 但我仍然有const

Trying to just use char* : 试图只使用char*

char* name;
name = GetName();

I get invalid conversion from 'const char*' to 'char*' . invalid conversion from 'const char*' to 'char*' What's the best habit for this kind of conversion? 这种转换的最佳习惯是什么?

The best habit for this kind of conversion is to use std::string throughout your code. 这种转换的最佳习惯是在整个代码中使用std::string Since the framework that you are using takes const char* as its input, you can always pass it the results of c_str() call on your 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;
}

A distant second best is using const char* in your code: 遥远的第二好是在你的代码中使用const char*

const char* name = GetName();

Since the framework that you are using takes const char* you are good here as well. 由于您使用的框架采用const char*您也很好。

If you need a non-const pointer, there is no way around copying the string. 如果需要非const指针,则无法复制字符串。 You can make a function that does it for you, but you would remain responsible for freeing the copies that you get from it: 您可以为您创建一个功能,但您仍然有责任释放您从中获得的副本:

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"; returns a pointer to a read-only string literal . 返回指向只读字符串文字的指针。

If you're using a function that takes a char* as an input, and you have a const char* (such as a read-only string literal), then you ought to supply a deep copy of the string starting at that const char* to such functions. 如果您正在使用一个以char*作为输入的const char* ,并且您有一个const char* (例如只读字符串文字),那么您应该提供从该const char*开始的字符串的深层副本const char*这些功能。

Else you risk undefined behaviour at runtime if a function attempts to modify a read-only string. 否则,如果函数尝试修改只读字符串,则会在运行时冒未定义的行为。

What you currently have is adequate; 你现在拥有的是足够的; assuming you can't work with std::string . 假设您无法使用std::string (If you can work with std::string and all your framework functions take a const char* input, then I'd suggest your refactoring your code to use a std::string , and pass the output of the c_str() method on that string class to your framework functions.) (如果您可以使用std::string 并且所有框架函数都使用const char*输入,那么我建议您重构代码以使用std::string ,并传递c_str()方法的输出那个字符串类到你的框架函数。)

Finally, if some of your framework functions require a char* then you could always build yourself a small adapter class: 最后,如果你的一些框架函数需要一个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;
};

Then for a function void foo(char* c) , you can call foo(Adapter("Hello"/*or any const char* */)); 然后对于函数void foo(char* c) ,可以调用foo(Adapter("Hello"/*or any const char* */)); and foo can do as it pleases with the char* that's embedded in the anonymous temporary! foo可以随意嵌入匿名临时的char* You could even enhance this class to take a constructor to a char* where in that case only a shallow copy of the pointer is taken (and the destructor doesn't delete the memory). 您甚至可以增强此类以将构造函数转换为char* ,在这种情况下,只会获取指针的浅表副本(并且析构函数不会删除内存)。

In C++, the typical way to "drop const " is by using const_cast<> : 在C ++中,“删除const ”的典型方法是使用const_cast<>

char *name = const_cast<char*>(GetName());

This is, of course, frowned upon, ugly and potentially dangerous, since it's really possible that GetName() returns a pointer to something that shouldn't be changed , and then you go and give yourself permission to change it. 当然,这是不受欢迎的,丑陋的和潜在的危险,因为GetName()确实可以返回指向不应该更改的内容的指针,然后你去允许自己更改它。 It's a good way to get very hard to find bugs, in that case. 在这种情况下,这是一个很难找到错误的好方法。

A workaround is to use a std::string as a temporary holding area; 解决方法是使用std::string作为临时保留区域; it will mean copying the string but that might be acceptable performance-wise: 这将意味着复制字符串,但这可能是性能可接受的:

std::string s(GetName());
char *name = s.c_str();

This will of course only work if name isn't kept around when s goes out of scope. 这当然只有在s超出范围时不保留name时才有效。 If that is the case, then you're going to have some form of persistent string storage layer. 如果是这种情况,那么您将拥有某种形式的持久性字符串存储层。

You could explicitly cast it. 你可以明确地施展它。 (char*) getName() . (char*) getName() But you probably shouldn't. 但你可能不应该这样做。 Because the const bit means something like "promise not to change it". 因为const位意味着“承诺不改变它”。 So if i have a function void foo(const char* string) I am saiying: "give me a pointer to a string. I won't change it." 所以如果我有一个函数void foo(const char* string)我正在说:“给我一个指向字符串的指针。我不会改变它。” And if you declare a variable const char* string = "hello"; 如果你声明一个变量const char* string = "hello"; You are saying, this string should not be changed. 你是说,不应该改变这个字符串。 And because you make this promise, the compiler knows, and can make your code more efficient. 因为你做出了这个承诺,编译器知道,并且可以使你的代码更有效率。 This is why: 这就是为什么:

const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true

your compiler knows you won't change a or b so it makes them point to the same address, so it only has to store one "hello" string. 你的编译器知道你不会改变ab所以它使它们指向同一个地址,所以它只需要存储一个"hello"字符串。 If you now go about changing a , b gets also changed, and this is not what you wanted. 如果你现在要改变ab也会改变,这不是你想要的。

So long story short, if you are absolutely sure that the function your calling does not change the string, you can explicitly cast it. 长话短说,如果你绝对确定你的调用函数没有改变字符串,你可以明确地转换它。 (or better, change the function to (const char*) if it's yours). (或者更好的是,将函数更改为(const char*)如果它是你的)。
If your not sure, you will have to make a copy. 如果你不确定,你将不得不复制。 (Like you are already doing with strcpy() ). (就像你已经在使用strcpy() )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM