带有 C 函数的 std::string_view

Posted

技术标签:

【中文标题】带有 C 函数的 std::string_view【英文标题】:std::string_view with C Fuction 【发布时间】:2019-05-07 20:54:11 【问题描述】:

我在 C++ 项目中使用了一些 C 遗留代码。

关于使用过的 C 函数看起来是这样的

void Add_To_log(const * const char pString_1, const * const char pString_2, int number);

现在当我像这样从 C++ 代码调用这个函数时

foo()

     Add_To_log("my first string", "my second string", 2);

我收到编译器警告 ISO C++ 禁止将字符串转换为字符。 所以为了摆脱这个,我想用 string_view 创建一个 c++ 包装器,以避免对我的字符串进行不必要的处理

void CPP_Wrapper(const string_view& string1, const string_view& string2, int number)

    Add_To_log(string1, string2, 2);

现在,如果我正确理解了引用,string_view 不一定包含终止空字符,这对于所有 c 函数都是必不可少的,因为它不拥有字符串对象。它只是显示它。

但是我可以假设在我的特殊情况下 string1 和 string2 是空终止的吗?

【问题讨论】:

你是先尝试 std::string::data() 还是 std::string::c_str() ? 这一行(单独)无法编译:void Add_To_log(const * const char pString_1, const * const char pString_2, int number); 请阅读如何发布minimal reproducible example 我认为创建一个看起来像一件事但有隐藏要求的界面是危险的。 你在编造一些东西。假设Add_To_log 的声明正确,您为foo() 提供的代码不会触发任何警告。绝对没有像“ISO C++ 禁止将字符串转换为字符”这样的东西。你为什么还要谈论string_view?除了缺少返回类型之外,您的 foo() 非常好,并且可以在没有任何诊断消息的情况下进行编译。你的问题是什么? 大概他们正在将 std::string 传递给一个采用 const char* 的函数,并且不知道 std::string 具有使这变得容易的函数。 (而且 C 函数原型显然也是错误的) 【参考方案1】:

但是我可以假设在我的特殊情况下 string1 和 string2 是空终止的吗?

没有。你不应该假设一个字符串视图是空终止的。如果 C 函数需要一个以 null 结尾的字符串,那么您建议的包装函数会适得其反。


关于使用过的 C 函数看起来是这样的

void Add_To_log(const * const char pString_1, const * const char pString_2, int number);

该声明格式错误。如果您将其修复为:

void Add_To_log(const char * const  pString_1, const char * const pString_2, int number)

那么这个调用是格式正确的:

Add_To_log("my first string", "my second string", 2); // No problem

【讨论】:

【参考方案2】:

std::string 已经有函数来提供指向旧 C 库函数的指针

http://www.cplusplus.com/reference/string/string/data/

这些提供了一个非拥有的只读指针,适用于在函数调用期间需要只读访问的大多数 C 库函数。我假设 std::string 的生命周期比函数调用更长,并且指针仅在函数调用期间使用。或者正如我上面链接的文档所述,“返回的指针可能会因进一步调用修改对象的其他成员函数而失效。” (显然包括析构函数)

另外,请注意在 c++98 构建中使用 c_str(),因为 data() 直到 c++11 才保证终止 null,如文档链接和 eerorika 中所述。

#include <stdio.h>
#include <string>

extern "C" 
    void legacy_logger(const char * const pstr) 
        printf("%s\n", pstr);
    


int main()

    std::string message "This is the string." ;
    legacy_logger(message.data());

【讨论】:

除非legacy_logger 存储指针供以后使用。 (这不太可能给出名称,但在一般情况下......) 好点,我应该明确假设,而不仅仅是链接文档。 另外,在 C++11 之前,string::data 不能保证为空终止。如果需要考虑向后兼容性,则应使用string::c_str 也就是说,如果提问者正在考虑使用 std::string_view,在 c++ 17 中是全新的,那么未终止的 data 应该不是问题。

以上是关于带有 C 函数的 std::string_view的主要内容,如果未能解决你的问题,请参考以下文章

c++17比较string_view和string时的歧义

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

真的没有来自 std::string_view 的 std::string 的显式构造函数吗?

将函数参数 `const char*` 转换为 `std::string_view` 是不是安全?

将 std::string 的 xvalue 传递给采用 std::string_view 的函数