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

C++ union 的一種妙用法

 更新時(shí)間:2026年07月01日 08:25:08   作者:流星雨愛編程  
本文探討了C++中union的特殊用法,通過分析標(biāo)準(zhǔn)庫中的constant_init模板結(jié)構(gòu)體,揭示了union在編譯期常量初始化中的巧妙應(yīng)用,感興趣的可以了解一下

1.背景

union,人皆知而鮮用的一個(gè)類。我最近在閱讀C++標(biāo)準(zhǔn)庫的源碼時(shí),看到了如下實(shí)現(xiàn):

template<typename T>
struct constant_init {
    union {
        T obj;
    };
    constexpr constant_init() : obj() {}

    ~constant_init() { /* do nothing, union object is not destroyed */}
};

constant_init 用來在編譯期創(chuàng)建一個(gè)類型 T 的對象 obj,obj 就放在了匿名的 union 中。為何要把一個(gè)對象放在 union 中?只因不想讓該對象被銷毀。

union 便有此用,標(biāo)準(zhǔn)描述為:

Absent default member initializers, if any non-static data member of a union has a non-trivial default constructor, copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, the corresponding member function of the union will be implicitly deleted unless it is user-provided.
在沒有默認(rèn)成員初始化器的情況下,如果 union 的任一非靜態(tài)數(shù)據(jù)成員具有非平凡的默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、移動(dòng)構(gòu)造函數(shù)、拷貝賦值運(yùn)行符、移動(dòng)賦值運(yùn)算符或析構(gòu)函數(shù),則其相應(yīng)的成員函數(shù)將被隱式刪除(除非用戶顯式定義)。

例如:

union S {
    int a;
    std::string str;
};

S 無法使用,因?yàn)?std::string 導(dǎo)致它的對應(yīng)成員函數(shù)被隱式刪除了。

可以通過以下方式來解決。

1.使用 default member initializer

union S {
    int a;
    std::string str = "union str"; // default member initializer
    ~S() {} // explicitly define a destructor
} s;

std::cout << s.str;

default member initializer 會(huì)構(gòu)造一個(gè) std::string 對象,于是成員 str 處于激活狀態(tài)。此時(shí),S 的默認(rèn)構(gòu)造函數(shù)不會(huì)被刪除,但析構(gòu)函數(shù)依舊被移除,需要顯式寫出(但 std::string 依舊不會(huì)被析構(gòu),必須顯式調(diào)用析構(gòu))。

2.聚合初始化

union S {
    std::string str;
    int a;
    ~S() {} // explicitly define a destructor
} s = { "union str"s };

std::cout << s.str;

此時(shí),S 的構(gòu)造函數(shù)也被刪除了。但是,聚合初始化能夠初始化構(gòu)造函數(shù)被刪除的對象,聚合初始化的類本身就不允許有構(gòu)造函數(shù)。

需要注意,union 的聚合初始化,默認(rèn)初始化第一個(gè)成員,所以 str 被挪到最前面了。

3.顯式寫出被刪除的函數(shù)

這個(gè)就不必給例子了。

2.核心作用與設(shè)計(jì)意圖

該模板結(jié)構(gòu)體是 C++ 編譯期常量初始化的包裝器,核心目標(biāo)是讓任意類型 T 支持 constexpr(編譯期)默認(rèn)初始化,同時(shí)通過 union 特性避免自動(dòng)調(diào)用 T 的析構(gòu)函數(shù),適用于需編譯期構(gòu)造且手動(dòng)管理生命周期的場景。

3.關(guān)鍵設(shè)計(jì)

  • union 的妙用:僅包含單個(gè)成員 T obj,利用 union 的特性 —— 編譯器不會(huì)自動(dòng)調(diào)用成員的析構(gòu)函數(shù)(因 union 無法確定活躍成員),因此析構(gòu)函數(shù) ~constant_init() 空實(shí)現(xiàn)是合理的,避免誤調(diào)用 obj 的析構(gòu)。
  • constexpr 構(gòu)造函數(shù):C++11 及以上支持 constexpr 構(gòu)造函數(shù),obj() 是 T 的值初始化(零初始化 + 默認(rèn)初始化),確保編譯期可構(gòu)造(需 T 的默認(rèn)構(gòu)造滿足 constexpr 要求或?yàn)槠椒矘?gòu)造)。
  • 內(nèi)存布局:因 union 僅一個(gè)成員,constant_init<T> 的大小、對齊方式與 T 完全一致,無額外內(nèi)存開銷。

4.適用場景與代碼示例

1.適用條件(必須同時(shí)滿足)

  • T 是 平凡析構(gòu)類型(std::is_trivially_destructible_v<T> 為 true),否則會(huì)導(dǎo)致內(nèi)存泄漏(obj 的析構(gòu)未被調(diào)用)。
  • T 需支持編譯期默認(rèn)初始化(要么是內(nèi)置類型 / POD,要么自定義 constexpr T())。

2.典型用法

#include <type_traits>

// 原結(jié)構(gòu)體(添加靜態(tài)斷言增強(qiáng)安全性)
template<typename T>
struct constant_init {
    static_assert(std::is_trivially_destructible_v<T>, 
                  "T must be trivially destructible to avoid memory leak");
    union {
        T obj;
    };
    // C++14+ 支持 constexpr 構(gòu)造函數(shù)初始化列表
    constexpr constant_init() : obj() {}
    // 禁止隱式析構(gòu) union 成員
    ~constant_init() {}
};

// 示例1:內(nèi)置類型(編譯期初始化)
constexpr constant_init<int> ci_int; // ci_int.obj = 0(零初始化)
static_assert(ci_int.obj == 0, "compile-time check");

// 示例2:自定義 POD 類型
struct POD { int x; double y; };
constexpr constant_init<POD> ci_pod; // ci_pod.obj.x=0, ci_pod.obj.y=0.0

// 示例3:constexpr 自定義類型
struct ConstExprType {
    constexpr ConstExprType() : val(42) {}
    int val;
};
constexpr constant_init<ConstExprType> ci_cexpr;
static_assert(ci_cexpr.obj.val == 42, "compile-time check");

5.潛在風(fēng)險(xiǎn)與限制

1.非平凡析構(gòu)類型禁用

若 T 是非平凡析構(gòu)(如 std::string、std::vector),使用該結(jié)構(gòu)體將導(dǎo)致內(nèi)存泄漏(obj 的析構(gòu)函數(shù)未被調(diào)用):

// 錯(cuò)誤示例:std::string 是非平凡析構(gòu)
constant_init<std::string> ci_str; // 構(gòu)造時(shí)初始化空字符串(運(yùn)行時(shí))
// 析構(gòu)時(shí)未調(diào)用 std::string 的析構(gòu),內(nèi)存泄漏

2.constexpr 失效場景

若 T 的默認(rèn)構(gòu)造不是 constexpr(如包含動(dòng)態(tài)內(nèi)存分配),constant_init 的構(gòu)造函數(shù)將退化為運(yùn)行時(shí)調(diào)用,失去編譯期初始化優(yōu)勢。

3.復(fù)制 / 移動(dòng)語義缺失

默認(rèn)生成的復(fù)制構(gòu)造 / 賦值運(yùn)算符會(huì)淺拷貝 obj,若 T 需深拷貝(如自定義帶指針的類型),需手動(dòng)實(shí)現(xiàn)拷貝邏輯,否則會(huì)導(dǎo)致淺拷貝問題。

6.注意事項(xiàng)

1.添加靜態(tài)斷言(如上文示例),強(qiáng)制檢查 T 是平凡析構(gòu)類型,避免誤用。

2.手動(dòng)實(shí)現(xiàn)復(fù)制 / 移動(dòng)語義(若 T 需深拷貝):

constexpr constant_init(const constant_init& other) : obj(other.obj) {}
constant_init& operator=(const constant_init& other) {
    obj = other.obj;
    return *this;
}

3.若需支持 C++20+,直接使用 std::optional 替代,無需自定義結(jié)構(gòu)體。

到此這篇關(guān)于C++ union 的一種妙用法的文章就介紹到這了,更多相關(guān)C++ union用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++浮點(diǎn)數(shù)類型詳情

    C++浮點(diǎn)數(shù)類型詳情

    這篇文章主要介紹了C++浮點(diǎn)數(shù)類型,浮點(diǎn)數(shù)是C++的第二組基本類型,它能夠表示帶小數(shù)部分的數(shù)字。不僅如此,浮點(diǎn)數(shù)的范圍也比int更大,可以表示更大范圍的數(shù)字。下面來我們大家一起來學(xué)習(xí)學(xué)習(xí)內(nèi)容
    2021-11-11
  • 淺談int8_t int64_t size_t ssize_t的相關(guān)問題(詳解)

    淺談int8_t int64_t size_t ssize_t的相關(guān)問題(詳解)

    下面小編就為大家?guī)硪黄獪\談int8_t int64_t size_t ssize_t的相關(guān)問題(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • C++11原子操作詳解

    C++11原子操作詳解

    這篇文章主要為大家介紹了C++的原子操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • C++用指針變量作為函數(shù)的參數(shù)接受數(shù)組的值的問題詳細(xì)總結(jié)

    C++用指針變量作為函數(shù)的參數(shù)接受數(shù)組的值的問題詳細(xì)總結(jié)

    以下是對C++中用指針變量作為函數(shù)的參數(shù)接受數(shù)組的值的問題進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • 關(guān)于C語言操作符的那些事(超級(jí)全)

    關(guān)于C語言操作符的那些事(超級(jí)全)

    這篇文章主要給大家介紹了關(guān)于C語言操作符的那些事兒,c語言的操作符有很多,包括算術(shù)操作符、移位操作符、位操作符、賦值操作符、單目操作符、關(guān)系操作符、邏輯操作符、條件操作符、逗號(hào)表達(dá)式、下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員,需要的朋友可以參考下
    2021-08-08
  • C?C++輸入輸出基礎(chǔ)教程示例詳解

    C?C++輸入輸出基礎(chǔ)教程示例詳解

    當(dāng)我們在網(wǎng)站做題的時(shí)候經(jīng)常會(huì)遇到各種要求的輸入輸出,而且會(huì)有時(shí)間超限等多個(gè)問題,這時(shí)我們就要優(yōu)化我們的輸入輸出或者規(guī)范我們的輸入輸出格式,下面介紹C和C++中的輸入輸出問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-11-11
  • C語言函數(shù)的聲明、定義、調(diào)用方式

    C語言函數(shù)的聲明、定義、調(diào)用方式

    本文詳細(xì)介紹了如何在不同情況下定義和使用函數(shù),包括無返回值和有返回值的無參及有參函數(shù),以及如何將數(shù)組作為函數(shù)參數(shù),總結(jié)了兩種在Java中聲明和調(diào)用函數(shù)的方式
    2026-02-02
  • C/C++實(shí)現(xiàn)經(jīng)典象棋游戲的示例代碼

    C/C++實(shí)現(xiàn)經(jīng)典象棋游戲的示例代碼

    中國象棋是起源于中國的一種棋,屬于二人對抗性游戲的一種,在中國有著悠久的歷史。本文將利用C++實(shí)現(xiàn)這一經(jīng)典游戲,快跟隨小編一起學(xué)習(xí)一下吧
    2022-06-06
  • C++中的6種構(gòu)造函數(shù)舉例詳解

    C++中的6種構(gòu)造函數(shù)舉例詳解

    這篇文章主要介紹了C++中的6種構(gòu)造函數(shù)的相關(guān)資料,C++中構(gòu)造函數(shù)用于類對象初始化,類型包括默認(rèn)構(gòu)造函數(shù)、參數(shù)化構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)等,默認(rèn)構(gòu)造函數(shù)通常不需要參數(shù),編譯器會(huì)自動(dòng)生成,除非存在其他構(gòu)造函數(shù),需要的朋友可以參考下
    2024-10-10
  • C語言詳細(xì)講解指針數(shù)組的用法

    C語言詳細(xì)講解指針數(shù)組的用法

    在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-05-05

最新評(píng)論

钟山县| 黑河市| 五大连池市| 陈巴尔虎旗| 读书| 南华县| 沙坪坝区| 佛坪县| 微山县| 紫阳县| 东兰县| 清水县| 乌拉特前旗| 高安市| 汝州市| 铜梁县| 江油市| 泸州市| 福贡县| 呈贡县| 宁蒗| 和田市| 察隅县| 石台县| 永修县| 新巴尔虎左旗| 沁阳市| 陈巴尔虎旗| 广宗县| 韶山市| 东台市| 榆社县| 西和县| 横山县| 济南市| 陵水| 浪卡子县| 公安县| 于田县| 枞阳县| 新巴尔虎右旗|