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

Posted

技术标签:

【中文标题】将函数参数 `const char*` 转换为 `std::string_view` 是不是安全?【英文标题】:Is it safe to convert function parameter `const char*` to `std::string_view`?将函数参数 `const char*` 转换为 `std::string_view` 是否安全? 【发布时间】:2020-02-13 13:22:01 【问题描述】:

标题几乎说明了一切。

void f(const char*)

void f(std::string_view)

安全吗?如果没有,有什么陷阱?

std::string_view 语义规定数组不一定是空终止的,这可能是f 内部的一个真正问题,因为已考虑到这一点(例如,如果将原始指针传递给期望空终止的函数在f 内)。

【问题讨论】:

C++ 中没有什么是“安全的”。您必须充分了解每个更改的含义。只有您才能确定这在您的特定程序中是否“安全”。也许是,也许不是,只有你可以访问完整的程序,只有你自己才能弄清楚。 @SamVarshavchik 这个问题是在普遍接受的语义范围内。 问题是,如果你问两个C++开发者“X”是否是“普遍接受的”,你会得到三个不同的答案。 你会在 cmets 部分得到它们。 【参考方案1】:

安全吗?

是的,只要它是正确的,它就是安全的。如果有人给你垃圾,你仍然会有垃圾。

有什么陷阱?

正如您所说,std::string_view 不需要以空值结尾。如果您在调用链的某个位置需要一个以空结尾的 c 字符串,那么您不能使用它,因为您不能保证您会拥有一个。

【讨论】:

根据字符串的大小,您可能只想拥有void f(std::string)。复制线性数据(类似数组)非常快,因此您甚至可能会根据用例注意到副本。 这不仅仅是一个副本,它也是[可能]一个动态分配和一些间接的。这加起来 const char* 也没有这样的保证。事实上,问题不在于调用链的更下方,它已被“移动”到就在此处,因为从没有长度参数的const char* 构造string_view 需要const char*指向一个终止的缓冲区。【参考方案2】:

安全吗?

一般不会。

如果没有,有什么陷阱?

这个:

std::string_view 语义规定数组不一定是空终止的,这可能是 f 内部的一个真正问题,因为已考虑到这一点(例如,如果将原始指针传递给期望内部空终止的函数f)。

只要函数的实现不依赖空终止,改变是安全的。

但如果实现确实依赖于 null 终止,那么在更改该实现之前,更改将是不安全的。

假设函数的实现不依赖空终止是不安全的。

【讨论】:

这不是真的; 已经 f 的前提条件是参数以空值结尾,因为我们没有提供长度参数。至于这是否会改变“安全性”,同样可以保证原始的const char* 指针被空终止。实际的问题是,如果它不是,则到string_view 的转换可能有UB,因此如果f 以前不依赖于被终止的输入,现在就可以了。所以这与你所说的相反;) there is already a precondition of f that the argument be null-terminated 这正是使更改不安全的原因:它删除了该前提条件。如果函数的实现依赖于该前提条件,这是一个问题。 if it weren't, the conversion to string_view probably has UB 构造一个非空终止的std::string_view 是非常好的定义。 If f did not previously rely on the input being terminated, it does now. API 绝对不保证更改后输入为空终止。 它不会删除该前提条件。函数的前提条件不限于其参数类型的前提条件。可以推断出f 必须 的前提条件是它的参数是一个指向 null-terminated 缓冲区的指针(即使const char* 本身不需要这个)。此代码更改并没有本质上改变该前提条件。 “构造一个非空终止的 std::string_view 是非常好的定义。” 不是来自const char*(没有大小参数)它不是'吨。想想那将如何运作。那就咨询eel.is/c++draft/string.view.cons#2 ;) @AsteroidsWithWings 这是一个技术问题。前提条件“std::string_view 必须引用以空字符结尾的字符串”是一个愚蠢的前提条件,不应该存在。

以上是关于将函数参数 `const char*` 转换为 `std::string_view` 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

求助:error C2664: “CreateWindowExW”: 不能将参数 3 从“const char [8]”转换为“LPCWSTR”

VS2008 C++中 inet_addr()函数用法。 inet_addr: 不能将参数 1 从“CString”转换为“const char *”

C++ 我将一个const char*的字符串转换为string出错

c++ 从 LPCTSTR 转换为 const char *

将字符串从 std::string 转换为 const char * 时出现数据丢失问题

在Qt中如何将QString转换为const char*