如何将std :: string传递给期望char *的函数?

时间:2010-11-30 18:51:28

标签: c++ visual-studio-2010 visual-c++

  

可能重复:
  Can I get a non-const C string back from a C++ string?

我需要先转换它吗?我在另一篇文章中看到,如果函数需要const char *,则可以使用.c_str()。那只是char *?

6 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:6)

无法从保证在所有平台上工作的字符串中获取char *,因为string不需要使用连续存储。< / p>

您最安全,最便携的做法是将字符串复制到所使用使用可靠存储空间(或许vector),然后使用它。

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

如果你想要hacky和非便携并且显然不安全,你可以确认你的string实现确实使用了有条件的存储,然后可以使用它:

&my_str[0]

但是我会打击任何为我工作的开发人员。

编辑:

我已经意识到目前没有已知的STL实现没有将字符串数据存储在连续的数组中,这将使&my_str[0]安全。在即将推出的C ++ 0x标准中,存储也必须是连续的。

也是如此(我被要求说明这一点)。

有人建议,因为如果这些事实证明我的帖子事实上是不正确的。

自己决定,但我拒绝。这不在当前 C ++标准中,因此不是必需的。我仍然会按照我的建议做事,并且在任何代码审查中,我都会标记任何假设底层存储是可靠的代码。

考虑一下。假设有一个关于vtable指针的问题。有人想通过查看vtable来检查一个类并获得指向虚函数的指针。我会立即告诉他们不要这样做,因为没有提到如何在C ++中实现虚拟方法。我所知道的每个实现都使用vtable,我想不出更好的方法。多态性很可能永远使用vtable实现。这样可以直接检查vtable吗?

IMO不,因为这取决于未记录的实施细节。你无法控制它,它可能随时改变。即使你预计它永远不会改变,依靠这些实现细节仍然是糟糕的工程。

自己决定。

答案 2 :(得分:1)

当一个参数被声明为char *时,隐含地假设该函数将对指向的字符串的修改产生副作用。基于此以及c_str()不允许对包含的字符串进行修改这一事实,您无法将std :: string显式传递给此类方法。

通过以下方法可以实现这样的事情:

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

答案 3 :(得分:1)

有三种情况:


如果函数不在您的控件之内,并且它修改了字符串,或者您没有,也无法知道它是否修改了字符串:

然后,将字符串复制到临时缓冲区,并将其传递给函数,如下所示:

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

如果函数不在您的控件之内,但您某些它不会修改字符串,并且不将参数作为const而只是API的错误。

然后,你可以抛弃const并将其传递给函数

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

您可以控制该功能(更改签名不会造成过于破坏)。

在这种情况下,更改函数以接受string&(如果它修改输入缓冲区)或const char*const string&,如果不是。

答案 4 :(得分:0)

如果您确定不会修改char *,则可以使用const_cast删除const。

答案 5 :(得分:0)

这是一个肮脏的解决方案,但我猜它有效

std::string foo("example");

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

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