标题:将临时 std::string 传递给接受 std::string_view 的函数是否安全?
身体:
我正在开发一个 C++ 程序,并且对将 std::string 传递给接受 std::string_view 的函数的安全性有疑问。这是我的代码: 我做了一些
#include<bits/stdc++.h>
using namespace std;
void foo(string_view sv) {
}
int main() {
foo(string("abc"));//is it safe?
return 0;
}
在此示例中,我创建一个临时 std::string 对象并将其传递给 foo 函数,该函数采用 std::string_view 作为参数。我知道 std::string_view 是对字符串的非拥有引用。
这是另一个关于 leetcode 问题的问题。
#include<ranges>
class Solution {
public:
vector<int> smallestTrimmedNumbers(vector<string> &nums, vector<vector<int> > &queries) {
vector<int> ans;
auto cmp = [&](auto &a, auto &b) {
if (a.first == b.first) return a.second < b.second;
return a.first < b.first;
};
for (auto &&q: queries) {
int k = q[0], t = q[1];
vector<pair<string_view, int> > p;
for (int i = 0; i < nums.size(); ++i) {
p.push_back(make_pair(string_view(nums[i]).substr(nums[i].size() - t), i));
}
ranges::nth_element(p, p.begin() + k - 1, cmp);
ans.push_back(p[k - 1].second);
}
return ans;
}
};
p.push_back(make_pair(string_view(nums[i]).substr(nums[i].size() - t), i));
使用 string_view(nums[i]) 从 nums[i] 创建 string_view,然后使用 substr(nums[i].size() - t) 提取最后 t 个字符。为什么需要 string_view(nums[i]) ?难道我们不能直接在 nums[i] 上调用 substr 而不创建 string_view 吗?
我的问题是: 将临时 std::string 传递给采用 std::string_view 的函数是否安全?临时 std::string 的生命周期是否会在函数调用期间延长,或者是否有可能出现未定义的行为?
我希望详细解释 std::string_view 如何与临时对象交互,以及避免潜在问题的任何最佳实践。
将临时 std::string 传递给 std::string_view 是不安全的,因为临时字符串被破坏,使 std::string_view 带有悬空引用。确保字符串的寿命足够长,以使 std::string_view 有效。
示例
void foo(std::string_view sv) {
// Do something with sv
}
int main() {
foo(std::string("abc")); // Unsafe: temporary string is destroyed after this line
}
更安全的方法
int main() {
std::string name = "abc"; // Safe: 'name' has a longer lifetime
foo(name); // Safe: 'name' is valid for the entire scope of foo()
return 0;
}
string_view 的工作
原始字符串的任何变化都会直接反映在string_view中,因为string_view直接指向字符串内存地址。
string_view 中的任何更改都不会反映在原始字符串中,它会创建自己的视图,并且会在其中进行更改,而不是原始字符串。
所以总而言之,直接将字符串传递给 string_view 是不安全的,因为它会一直存在,直到该行执行之后它才无效,因此最好在传递字符串之前声明该字符串,以便在函数调用后生命仍然存在。