将函数参数 `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 *