开发者

How do I pass an std::string to a function that expects char*? [duplicate]

This question already has answers here: Closed 12 years ago.

Possible Duplicate:

Can I get a non-const C string back from a C++ string?

Do I need to convert it first? I saw in another post t开发者_C百科hat .c_str() can be used if the function expected const char*. What about for just char*?


std::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());


There is no way to get a char* from a string that is guaranteed to work on all platforms, for the simple fact that string is not required to use contiguous storage.

Your safest, most portable course of action is to copy the string somewhere that does use contigious storage (a vector perhaps), and use that instead.

vector<char> chars(my_string.begin(), my_string.end());
char* ptr = &chars[0];

If you want to be hacky and non-portable and decidedly unsafe, you can confirm that your string implementation does in fact use contigious storage, and then maybe use this:

&my_str[0]

But I would punch any developer that worked for me that did this.

EDIT:

I've been made aware that there are currently no known STL implementations that do not store the string data in a contiguous array, which would make &my_str[0] safe. It is also true (and I was asked to state this) that in the upcoming C++0x standard, it will be required for the storage to be contiguous.

It's been suggested that because if these facts that my post is factually incorrect.

Decide for yourself, but I say no. This is not in the current C++ standard, and so it is not required. I will still in practice do things the way I have suggested, and in any code review I will flag any code that assumes the underlying storage is contigious.

Consider this. Suppose there were a question about vtable pointers. Someone wants to examing a class and get the pointer to a virtual function by looking at the vtable. I would immediately tell them not to do this because there is no mention of how virtual methods are implemented in C++. Every implementation I know uses vtables, and I can't think of a better way to do it. It is likely that polymorphism will forever be implemented using vtables. Does that make it ok to examing the vtable directly?

IMO no, because this depends on undocumented implementation details. You have no control over this, and it could change at any time. Even if you expect it will never change, it is still bad engineering to rely on these implementation details.

Decide for yourself.


There are three scenarios:


If the function is outside of your control, and it either modifies the string, or you don't and can't know if it modifies the string:

Then, copy the string into a temporary buffer, and pass that to the function, like so:

void callFoo(std::string& str);
{
    char* tmp = new char str(str.length() +1);
    strncpy(tmp, str.c_str(), str.length());
    foo(tmp);
    // Include the following line if you want the modified value:
    str = tmp;
    delete [] tmp;
}

If the function is outside of your control, but you are certain it does not modify the string, and that not taking the argument as const is simply a mistake on the API's part.

Then, you can cast the const away and pass that to the function

void callFoo(const std::string& str)
{
    foo(const_cast<char*> str.c_str());
}

You are in control of the function (and it would not be overly disruptive to change the signature).

In that case, change the function to accept either a string& (if it modifies the input buffer) or either const char* or const string& if it does not.


When a parameter is declared as char* there it is implicitly assumed that the function will have as a side effect the modification of the string that is pointed. Based in this and the fact that c_str() does not allow modifications to the enclosed string you cannot explicitly pass an std::string to such a method.

Something like this can be achived by following the following approach:

#include <cstdlib>
#include <string>
#include <iostream>

void modify_string(char* pz)
{
    pz[0] = 'm';
}

class string_wrapper
{
    std::string& _s;
    char* _psz;
    string_wrapper(const string_wrapper&);
    string_wrapper& operator=(const string_wrapper&);
public:

    string_wrapper(std::string& s) : _s(s), _psz(0) {}

    virtual ~string_wrapper()
    {
        if(0 != _psz)
        {
            _s = _psz;
            delete[] _psz;
        }
    }

    operator char*()
    {
        _psz = new char[_s.length()+1];
        strcpy(_psz,_s.c_str());
        return _psz;
    }
};


int main(int argc, char** argv)
{
    using namespace std;
    std::string s("This is a test");
    cout << s << endl;
    modify_string(string_wrapper(s));
    cout << s << endl;
    return 0;
}


If you are certain that the char* will not be modified, you can use const_cast to remove the const.


It's a dirty solution but I guess it works

std::string foo("example");

char* cpy = (char*)malloc(foo.size()+1);

memcpy(cpy, foo.c_str(), foo.size()+1);

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜