std::string::c_str中无法将“const char *”转换为“char *”

3
这会出现错误:无法将“const char *”转换为“char *”。
class Mock
{
public:
    ...
    static void func(char **result)
    {
          *result = (resultsI++)->c_str();
    }
static std::vector<std::string> results;
static std::vector<std::string>::iterator resultsI;
};

std::vector<std::string> Mock::results;
std::vector<std::string>::iterator Mock::resultsI;

我该如何有效地消除这个错误,而不改变函数func的接口?这个接口的实现者:

void (func*)(char **result) 

忘记在签名中使用const char **。我无法更改它。

请记住,这只是一个模拟,并且仅用于我的单元测试。


你只能复制而不能使用 c_str() - chris
你可以(但不应该)去掉 const 属性(const_cast<char*>((resultsI++)->c_str());)。 - Ryan Guthrie
Ryan Guthrie:我为什么不能这样做? - Baz
const 是为了保护你自己而存在的。如果你将其强制转换,就会失去这种保护。 - wardd
3个回答

6

尝试:

*result = &(*resultsI++)[0];

虽然在C++11之前不能保证这样做可以正常工作,但是已知在大多数或所有当前编译器中都可以。

危险在于如果该函数尝试更改字符串的长度,可能会导致一些不良错误。更改单个字符应该是可以的。


那么只有C++11规定了std::string必须具有连续的内存吗? - Kos
@Kos:没错。虽然我熟悉的大多数 C++03 实现实际上都使用连续存储,但这在 C++03 标准中并不保证。当我需要 C++03 保证连续存储时,我通常使用 vector<char> 而不是 string - John Dibling
@Kos,保证是在对所有委员会成员进行调查后,根据他们的std::string实现已经符合要求的情况下,添加到C++11中的。 - Mark Ransom
@JohnDibling,我也用过vector<char>,这取决于任务。有时它很好用,但有时没有字符串方法会让它变得繁琐。 - Mark Ransom
3
这里的危险在于对原始字符串的任何修改都可能导致其移动,而无法保证它以 '\0' 结尾,这可能会在将其传递给 C-String 函数时成为问题。如果我要执行这样危险的操作,我希望能让它显而易见地表明它是危险的。通过使用 const_cast<char*>((resultsI++)->c_str()),你可以使其突出显示,因为我们知道不应该使用 const 强制转换。这样你就知道你的代码很糟糕,并且很明显。 - Martin York

4

如果你非常确定接口函数不会修改字符串,那么可以使用

*result = const_cast<char *>((resultsI++)->c_str());

要移除const属性。否则,另一个选择是从使用std::vector<std::string>转换为std::vector<std::vector<char>>,但您必须确保正确地将字符串空终止。

4
在测试代码中,如果你确定接口的用户不会改变char*,那么你可以使用const_cast。这假设调用者没有拥有char*; 如果是这种情况,那么你应该进行复制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接