C++17 string_view关键字

std::string_view 是 C++17 引入的轻量级、非拥有(non-owning)的字符串视图类型,用于高效地观察现有字符串数据,而无需拷贝或管理内存。以下是其核心特性:


1. 非拥有性

  • string_view ​不持有字符串的所有权,仅通过指针和长度信息引用外部已有的字符序列(如 std::string、C 风格字符串等)。
  • 它不负责管理内存,因此不会分配或释放内存。

2. 只读性

  • string_view 是只读的,无法通过它修改底层字符串数据。
  • 所有操作(如访问、查找、比较等)均为只读。

3. 轻量级

  • string_view 对象通常仅包含两个成员:
    • 一个指向字符数据的指针(const char*)。
    • 一个表示长度的整数(size_t)。
  • 内存占用极小,构造和复制开销极低。

4. 高效性

  • 零拷贝操作:传递或处理字符串时避免内存分配和复制,尤其适合高频调用或大文本处理。
    void process(std::string_view sv); // 无需拷贝字符串
    process("Hello"); // 直接引用原始数据
  • 统一接口:兼容 std::stringconst char*、子字符串等多种输入类型,简化代码逻辑。

5. 生命周期依赖

  • string_view ​依赖被引用字符串的生命周期。如果被引用的字符串被销毁或修改,string_view 将变为悬空引用,导致未定义行为。
    std::string_view getView() {
        std::string temp = "temporary";
        return temp; // 危险:temp 被销毁后,返回的 string_view 无效
    }

6. 使用场景

  • 函数参数传递:当函数仅需读取字符串时,用 string_view 代替 const std::string& 或 const char*,减少临时对象构造。
  • 字符串处理:查找、比较、截取等操作(如解析日志、处理文本片段)。
  • 性能敏感场景:如内存映射文件处理或高频字符串操作,避免内存分配瓶颈。

7. 注意事项

  • 生命周期管理:确保引用的字符串数据在 string_view 使用期间有效,否则会导致悬空引用。
  • 空终止符问题string_view 不保证数据以 \0 结尾,需通过 size() 明确操作范围,或手动添加终止符。
  • 不适用于长期存储:若需保留字符串内容,应转换为 std::string

8. 与 std::string 的对比

特性​**std::string**​**std::string_view**
所有权拥有数据,管理内存仅引用外部数据
修改能力可读写只读
内存开销高(动态分配)极低(仅指针+长度)
适用场景长期存储、修改字符串短期观察、高频只读操作

9. 示例代码

#include <iostream>
#include <string>
#include <string_view>

void print(std::string_view sv) {
    std::cout << sv << std::endl;
}

int main() {
    std::string str = "Hello, World!";
    std::string_view sv1(str); // 引用 std::string
    std::string_view sv2("C-style string"); // 引用 C 风格字符串

    print(sv1); // 输出: Hello, World!
    print(sv2); // 输出: C-style string

    std::string_view sv3 = sv1.substr(0, 5); // 截取子字符串
    print(sv3); // 输出: Hello

    return 0;
}

总结

std::string_view 是 C++17 中提升字符串处理效率的关键工具,通过非拥有、只读的特性避免不必要的内存操作。适用于高频读取、临时观察字符串的场景,但需谨慎管理数据生命周期。在性能敏感的项目(如日志处理、解析器)中合理使用,可显著优化程序性能。

std::string_view 和 ​引用​(如 std::string& 或 const std::string&)在某些方面有相似之处,但它们的设计目的、行为和使用场景有显著区别。以下是详细对比:


1. 设计目的

  • ​**std::string_view**

    • 用于轻量级、非拥有地观察字符串数据,避免拷贝。
    • 不管理内存,仅通过指针和长度引用外部字符串。
    • 适合高频只读操作,如查找、比较、截取等。
  • 引用

    • 用于别名引用现有对象,可以是可修改的(std::string&)或只读的(const std::string&)。
    • 直接绑定到目标对象,访问时无需额外的指针和长度信息。
    • 适合需要修改或长期观察对象的场景。

2. 内存管理

  • ​**std::string_view**

    • 不管理内存,仅引用外部字符串数据。
    • 如果被引用的字符串被销毁,string_view 会变为悬空引用,导致未定义行为。
  • 引用

    • 不管理内存,但依赖于目标对象的生命周期。
    • 如果目标对象被销毁,引用会变为悬空引用,导致未定义行为。

3. 性能

  • ​**std::string_view**

    • 轻量级:仅包含指针和长度信息,构造和复制开销极低。
    • 零拷贝:传递或处理字符串时避免内存分配和复制。
  • 引用

    • 轻量级:直接绑定到目标对象,访问时无需额外的指针和长度信息。
    • 零拷贝:传递或处理对象时避免内存分配和复制。

4. 使用场景

  • ​**std::string_view**

    • 高频只读操作:如查找、比较、截取等。
    • 性能敏感场景:如日志处理、解析器等。
    • 兼容多种字符串类型:如 std::stringconst char*、子字符串等。
  • 引用

    • 需要修改对象:如通过 std::string& 修改字符串内容。
    • 长期观察对象:如通过 const std::string& 观察字符串内容。
    • 绑定到具体对象:如传递大型对象时避免拷贝。

5. 生命周期管理

  • ​**std::string_view**

    • 依赖被引用字符串的生命周期,需确保被引用的字符串在 string_view 使用期间有效。
  • 引用

    • 依赖目标对象的生命周期,需确保目标对象在引用使用期间有效。

6. 示例对比

​**std::string_view 示例**
#include <iostream>
#include <string>
#include <string_view>

void print(std::string_view sv) {
    std::cout << sv << std::endl;
}

int main() {
    std::string str = "Hello, World!";
    std::string_view sv(str); // 引用 std::string
    print(sv); // 输出: Hello, World!

    std::string_view sv2 = sv.substr(0, 5); // 截取子字符串
    print(sv2); // 输出: Hello

    return 0;
}
引用示例
#include <iostream>
#include <string>

void modify(std::string& str) {
    str += " (modified)";
}

void print(const std::string& str) {
    std::cout << str << std::endl;
}

int main() {
    std::string str = "Hello, World!";
    print(str); // 输出: Hello, World!

    modify(str); // 修改字符串
    print(str); // 输出: Hello, World! (modified)

    return 0;
}

7. 总结对比

特性​**std::string_view**引用
所有权非拥有非拥有
修改能力只读可读写(std::string&
内存开销极低(指针+长度)极低(直接绑定)
生命周期管理依赖被引用字符串依赖目标对象
使用场景高频只读操作、性能敏感场景修改对象、长期观察对象
兼容性兼容多种字符串类型绑定到具体对象

选择建议

  • 如果需要高频只读操作兼容多种字符串类型,使用 std::string_view
  • 如果需要修改对象长期观察对象,使用引用。
  • 无论选择哪种方式,都需确保目标对象的生命周期有效,避免悬空引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值