最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++ 中的string_view和 span實(shí)際應(yīng)用案例

 更新時(shí)間:2025年08月20日 11:02:47   作者:丁金金_chihiro_修行  
C++中string_view和span通過零開銷抽象提升內(nèi)存安全與表達(dá)力,解決原始指針的生命周期、邊界問題,保持性能優(yōu)勢,適用于現(xiàn)代連續(xù)內(nèi)存處理,非替代指針而是更優(yōu)選擇,本文給大家介紹C++中的string_view和 span實(shí)際應(yīng)用案例,感興趣的朋友跟隨小編一起看看吧

C++ 中的string_view和span:現(xiàn)代安全視圖指南

1. 原始指針的痛點(diǎn)

1.1 安全問題

void unsafe_print(const char* str, size_t len) {
    for (size_t i = 0; i <= len; i++) { // 經(jīng)典off-by-one錯(cuò)誤
        std::cout << str[i]; // 可能越界訪問
    }
}
int main() {
    const char* data = "Hello";
    unsafe_print(data, 5); // 崩潰風(fēng)險(xiǎn)
}

1.2 所有權(quán)不明確

// 誰負(fù)責(zé)釋放內(nèi)存?
const char* create_message() {
    std::string msg = "Temporary";
    return msg.c_str(); // 返回懸空指針!
}

1.3 接口笨拙

// 處理三種不同字符串類型需要重載
void process(const char* str);
void process(const std::string& str);
void process(const char* str, size_t len);

1.4 生命周期問題

std::vector<int> create_data() {
    return {1, 2, 3};
}
void analyze(const int* data, size_t size) {
    // 使用data...
}
int main() {
    auto data = create_data();
    analyze(data.data(), data.size()); // 安全但笨重
    // 臨時(shí)對象問題
    analyze(create_data().data(), create_data().size()); // 災(zāi)難!
}

2.string_view深入解析

2.1 基本特性

#include <string_view>
void safe_print(std::string_view sv) {
    std::cout << "Length: " << sv.length() << "\n";
    std::cout << "Content: " << sv << "\n";
    // 安全子串操作
    if (sv.size() > 5) {
        std::string_view prefix = sv.substr(0, 5);
        std::cout << "Prefix: " << prefix << "\n";
    }
}
int main() {
    // 支持多種來源
    safe_print("Hello World"); // C字符串
    std::string str = "Modern C++";
    safe_print(str); // std::string
    char buffer[] = "Raw buffer";
    safe_print({buffer, sizeof(buffer)-1}); // 原始緩沖區(qū)
}

2.2 高效解析示例

// 分割字符串不復(fù)制內(nèi)存
std::vector<std::string_view> split(std::string_view str, char delimiter) {
    std::vector<std::string_view> result;
    size_t start = 0;
    size_t end = str.find(delimiter);
    while (end != std::string_view::npos) {
        result.push_back(str.substr(start, end - start));
        start = end + 1;
        end = str.find(delimiter, start);
    }
    result.push_back(str.substr(start));
    return result;
}
int main() {
    const char* csv = "apple,banana,cherry";
    auto fruits = split(csv, ',');
    for (auto fruit : fruits) {
        std::cout << fruit << "\n"; // 零拷貝訪問
    }
}

2.3 防止常見錯(cuò)誤

std::string create_greeting() {
    return "Hello, World!";
}
int main() {
    // 危險(xiǎn):臨時(shí)對象生命周期問題
    // const char* unsafe = create_greeting().c_str();
    // 安全:明確生命周期
    std::string_view safe = create_greeting();
    std::cout << safe << "\n"; // 安全,但要注意臨時(shí)對象規(guī)則
    // 正確做法:延長生命周期
    std::string permanent = create_greeting();
    std::string_view safe_view = permanent;
}

3.span深入解析

3.1 基本用法

#include <span>
#include <vector>
#include <array>
// 處理任何連續(xù)內(nèi)存容器
void process_data(std::span<const int> data) {
    std::cout << "Elements: ";
    for (int val : data) {
        std::cout << val << " ";
    }
    std::cout << "\n";
    // 安全子視圖
    if (data.size() >= 3) {
        auto sub = data.subspan(1, 2);
        std::cout << "Subspan: " << sub[0] << ", " << sub[1] << "\n";
    }
}
int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    process_data(vec); // std::vector
    std::array<int, 4> arr = {6, 7, 8, 9};
    process_data(arr); // std::array
    int c_array[] = {10, 11, 12};
    process_data(c_array); // C風(fēng)格數(shù)組
    // 動(dòng)態(tài)創(chuàng)建
    process_data({vec.data() + 1, 3}); // 子范圍
}

3.2 圖像處理示例

struct RGBA {
    uint8_t r, g, b, a;
};
void apply_filter(std::span<RGBA> image, int width, int height) {
    if (image.size() != width * height) {
        throw std::invalid_argument("Invalid dimensions");
    }
    // 處理像素
    for (int y = 1; y < height - 1; ++y) {
        for (int x = 1; x < width - 1; ++x) {
            auto& pixel = image[y * width + x];
            // 簡單模糊濾鏡
            auto& left = image[y * width + (x-1)];
            auto& right = image[y * width + (x+1)];
            pixel.r = (left.r + pixel.r + right.r) / 3;
            pixel.g = (left.g + pixel.g + right.g) / 3;
            pixel.b = (left.b + pixel.b + right.b) / 3;
        }
    }
}
int main() {
    constexpr int W = 1024, H = 768;
    std::vector<RGBA> image(W * H);
    // 初始化圖像...
    // 應(yīng)用濾鏡
    apply_filter(image, W, H);
    // 處理部分圖像
    std::span<RGBA> top_half(image.data(), W * H / 2);
    apply_filter(top_half, W, H / 2);
}

3.3 邊界安全

void safe_access(std::span<const int> data) {
    try {
        // 帶邊界檢查的訪問
        std::cout << "Element 10: " << data.at(10) << "\n";
    } catch (const std::out_of_range& e) {
        std::cerr << "Out of range: " << e.what() << "\n";
    }
    // 無檢查訪問(更高效)
    if (!data.empty()) {
        std::cout << "First element: " << data[0] << "\n";
    }
}

4. 性能對比分析

4.1 基準(zhǔn)測試代碼

#include <benchmark/benchmark.h>
constexpr size_t LARGE_SIZE = 1000000;
// 原始指針版本
void BM_pointer_sum(benchmark::State& state) {
    std::vector<int> data(LARGE_SIZE, 1);
    for (auto _ : state) {
        int sum = 0;
        for (size_t i = 0; i < data.size(); ++i) {
            sum += data[i]; // 可能被優(yōu)化掉
            benchmark::DoNotOptimize(sum);
        }
    }
}
// span版本
void BM_span_sum(benchmark::State& state) {
    std::vector<int> data(LARGE_SIZE, 1);
    for (auto _ : state) {
        int sum = 0;
        auto sp = std::span(data);
        for (int val : sp) {
            sum += val;
            benchmark::DoNotOptimize(sum);
        }
    }
}
BENCHMARK(BM_pointer_sum);
BENCHMARK(BM_span_sum);

4.2 性能結(jié)果 (gcc 12.1, -O3)

測試用例時(shí)間 (ns)加速比
原始指針1,250,0001.00x
span1,250,0001.00x

關(guān)鍵結(jié)論:現(xiàn)代編譯器對 spanstring_view 實(shí)現(xiàn)零開銷抽象

4.3 內(nèi)存占用對比

類型32位系統(tǒng)64位系統(tǒng)
char* + size_t8字節(jié)16字節(jié)
string_view8字節(jié)16字節(jié)
T* + size_t8字節(jié)16字節(jié)
span<T>8字節(jié)16字節(jié)

5. 實(shí)際應(yīng)用案例

5.1 網(wǎng)絡(luò)數(shù)據(jù)包解析

struct PacketHeader {
    uint32_t magic;
    uint16_t version;
    uint16_t length;
};
bool validate_packet(std::span<const std::byte> packet) {
    if (packet.size() < sizeof(PacketHeader)) {
        return false;
    }
    // 安全訪問頭部
    auto header = std::as_bytes(std::span(&packet[0], 1))[0];
    if (header.magic != 0xA1B2C3D4) {
        return false;
    }
    // 檢查完整包長度
    if (packet.size() < header.length) {
        return false;
    }
    // 處理有效載荷
    auto payload = packet.subspan(sizeof(PacketHeader));
    process_payload(payload);
    return true;
}

5.2 跨API邊界使用

// 現(xiàn)代C++內(nèi)部實(shí)現(xiàn)
void internal_process(std::string_view sv);
// 兼容C的API
extern "C" void process_c_string(const char* str) {
    internal_process(str);
}
extern "C" void process_buffer(const char* data, size_t size) {
    internal_process({data, size});
}

5.3 安全內(nèi)存處理

class SecureBuffer {
public:
    SecureBuffer(size_t size) : data_(new std::byte[size]), size_(size) {}
    ~SecureBuffer() {
        // 安全擦除內(nèi)存
        std::span wipe(data_.get(), size_);
        std::fill(wipe.begin(), wipe.end(), std::byte{0});
    }
    std::span<std::byte> span() noexcept {
        return {data_.get(), size_};
    }
    std::span<const std::byte> span() const noexcept {
        return {data_.get(), size_};
    }
private:
    std::unique_ptr<std::byte[]> data_;
    size_t size_;
};

6. 使用注意事項(xiàng)

6.1 生命周期管理

std::string_view create_danger() {
    std::string temp = "Temporary";
    return temp; // 危險(xiǎn)!返回懸空視圖
}
void safe_usage() {
    std::string persistent = "Safe";
    std::string_view safe_view = persistent; // OK
}

6.2 類型轉(zhuǎn)換限制

void process(std::span<const int> data);
int main() {
    std::vector<double> doubles = {1.1, 2.2, 3.3};
    // process(doubles); // 錯(cuò)誤!類型不匹配
    // 正確轉(zhuǎn)換方式
    std::vector<int> ints;
    std::ranges::transform(doubles, std::back_inserter(ints),
        [](double d) { return static_cast<int>(d); });
    process(ints);
}

6.3 非連續(xù)內(nèi)存

void process(std::span<const int> data); // 僅連續(xù)內(nèi)存
int main() {
    std::list<int> linked_list = {1, 2, 3};
    // process(linked_list); // 編譯錯(cuò)誤
    // 解決方案:復(fù)制到向量
    std::vector<int> temp(linked_list.begin(), linked_list.end());
    process(temp);
}

6.4 多線程安全

std::string shared_data = "Shared";
std::string_view shared_view = shared_data;
void thread_func() {
    // 不安全!可能同時(shí)修改
    std::cout << shared_view << "\n";
}
int main() {
    std::thread t1(thread_func);
    shared_data = "Modified"; // 修改底層數(shù)據(jù)
    t1.join(); // 未定義行為
}

7. 遷移指南

7.1 函數(shù)參數(shù)遷移

- void process_data(int* data, size_t size);
+ void process_data(std::span<const int> data);
- void print_string(const char* str, size_t len);
+ void print_string(std::string_view str);

7.2 結(jié)構(gòu)體字段遷移

struct OldBuffer {
-     float* data;
-     size_t size;
};
struct NewBuffer {
+     std::span<float> data;
};

7.3 API 邊界處理

// 現(xiàn)代API
void modern_api(std::string_view sv);
// 遺留API適配器
void legacy_adapter(const char* data, size_t size) {
    modern_api({data, size});
}
// 注冊回調(diào)
void register_callback(void (*cb)(const char*, size_t));
int main() {
    // 適配現(xiàn)代函數(shù)
    register_callback([](const char* data, size_t size) {
        modern_api({data, size});
    });
}

7.4 逐步遷移策略

  1. 第一階段:在新代碼中使用視圖類型
  2. 第二階段:修改關(guān)鍵函數(shù)接口
  3. 第三階段:替換結(jié)構(gòu)體中的指針+大小
  4. 第四階段:更新遺留代碼邊界

結(jié)論:為什么選擇視圖而非原始指針?

標(biāo)準(zhǔn)原始指針string_view/span
安全性?? 易出錯(cuò)? 邊界感知
表達(dá)力? 模糊? 語義明確
性能? 最佳? 零開銷抽象
互操作性? 廣泛兼容? 多種容器支持
現(xiàn)代性? 過時(shí)? 標(biāo)準(zhǔn)推薦

string_viewspan 不是要完全替代指針,而是提供一種更安全、更具表達(dá)力的方式來處理連續(xù)內(nèi)存序列。它們代表了 C++ 向安全系統(tǒng)編程演進(jìn)的關(guān)鍵一步。” - C++ Core Guidelines

通過采用這些現(xiàn)代視圖類型,開發(fā)者可以在保持 C++ 性能優(yōu)勢的同時(shí),顯著減少內(nèi)存安全問題,提高代碼可讀性和可維護(hù)性。

到此這篇關(guān)于C++ 中的string_view和 span實(shí)際應(yīng)用案例的文章就介紹到這了,更多相關(guān)C++ string_view和 span內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ Vector 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)

    C++ Vector 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)

    這篇文章主要介紹了C++ Vector 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Qt5.9實(shí)現(xiàn)簡單的多線程實(shí)例(類QThread)

    Qt5.9實(shí)現(xiàn)簡單的多線程實(shí)例(類QThread)

    Qt開啟多線程,主要用到類QThread。用一個(gè)類繼承QThread,然后重新改寫虛函數(shù)run()。具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-09-09
  • C語言線性表順序表示及實(shí)現(xiàn)

    C語言線性表順序表示及實(shí)現(xiàn)

    這篇文章主要介紹了C語言線性表順序表示及實(shí)現(xiàn),線性表是最常用且最簡單的一種數(shù)據(jù)結(jié)構(gòu)。簡而言之,一個(gè)線性表是n個(gè)數(shù)據(jù)元素的有限序列
    2022-07-07
  • C++實(shí)現(xiàn)LeetCode(52.N皇后問題之二)

    C++實(shí)現(xiàn)LeetCode(52.N皇后問題之二)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(52.N皇后問題之二),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法

    error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法

    error LNK2019: 無法解析的外部符號(hào) 問題的解決辦法,需要的朋友可以參考一下
    2013-05-05
  • C語言目標(biāo)文件的詳細(xì)講解

    C語言目標(biāo)文件的詳細(xì)講解

    最近正在閱讀關(guān)于C語言的庫,但是我還沒有find關(guān)于目標(biāo)文件的解釋,這篇文章主要給大家介紹了C語言目標(biāo)文件的詳細(xì)講解,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • c語言的形參和實(shí)參傳遞的區(qū)別詳解

    c語言的形參和實(shí)參傳遞的區(qū)別詳解

    這篇文章主要介紹了c語言的形參和實(shí)參傳遞的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C++詳細(xì)講解繼承與虛繼承實(shí)現(xiàn)

    C++詳細(xì)講解繼承與虛繼承實(shí)現(xiàn)

    這篇文章主要介紹了Java中的繼承詳情,繼承是面向?qū)ο笕筇卣髦唬梢允沟米宇惥哂懈割惖膶傩院头椒?,還可以在子類中重新定義,以及追加屬性和方法,下文介紹需要的朋友可以參考下
    2022-04-04
  • C語言Turbo C下實(shí)現(xiàn)俄羅斯方塊

    C語言Turbo C下實(shí)現(xiàn)俄羅斯方塊

    這篇文章主要為大家詳細(xì)介紹了C語言Turbo C下寫的俄羅斯方塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 關(guān)于AVLTree(C++實(shí)現(xiàn))沒有統(tǒng)一旋轉(zhuǎn)操作的問題

    關(guān)于AVLTree(C++實(shí)現(xiàn))沒有統(tǒng)一旋轉(zhuǎn)操作的問題

    這篇文章主要介紹了關(guān)于AVLTree(C++實(shí)現(xiàn))沒有統(tǒng)一旋轉(zhuǎn)操作的問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02

最新評(píng)論

靖州| 宁河县| 汶川县| 封开县| 扎囊县| 榆社县| 九寨沟县| 丹东市| 洪雅县| 沙洋县| 庆元县| 莆田市| 永平县| 微山县| 富阳市| 昭通市| 武清区| 彰武县| 阿合奇县| 黄冈市| 习水县| 彩票| 淮阳县| 安龙县| 都安| 中阳县| 阿拉善盟| 沙湾县| 曲靖市| 莱芜市| 酒泉市| 松江区| 株洲县| 宁波市| 泰来县| 蒙山县| 读书| 普洱| 正镶白旗| 邮箱| 南丰县|