簡體   English   中英

如果使用 lambda,std::unique_ptr 如何沒有大小開銷

[英]How std::unique_ptr have no size overhead if using lambda

跟進這個問題,
std::unique_ptr 如何沒有大小開銷?

我做了以下代碼,結果出乎意料:

#include <memory>

#include <cstdio>

void f(void *p){
    free(p);
}

int main(){
    auto x1 = [](void *p){ free(p); };
    auto x2 = [](void *p){ f(p); };

    printf("%zu\n", sizeof(std::unique_ptr<int>                 )); //  8, expected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(&f)>   )); // 16, expected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(x1)>   )); //  8, unexpected
    printf("%zu\n", sizeof(std::unique_ptr<int, decltype(x2)>   )); //  8, unexpected
}

lambda 的最后兩種類型的大小為 8,即使它們與f()做同樣的事情。

這是怎么做的?

對 lambda 進行脫糖並簡化decltype ,您實際上寫道:

int main(){
    struct x1_impl {
        void operator()(void *p) { free(p); }
    };
    x1_impl x1;
    struct x2_impl {
        void operator()(void *p) { f(p); }
    };
    x2_impl x2;

    printf("%zu\n", sizeof(std::unique_ptr<int>));
    printf("%zu\n", sizeof(std::unique_ptr<int, void (*)(void*)>));
    printf("%zu\n", sizeof(std::unique_ptr<int, x1_impl>));
    printf("%zu\n", sizeof(std::unique_ptr<int, x2_impl>));
}

unique_ptr<T, Del>需要同時存儲T*Del 由於x1_implx2_impl沒有數據成員,它們不需要存儲,所以最后兩個unique_ptr可以只存儲一個T* 請注意, decltype(&f)void (*)(void*) ,但decltype(x1)是一個未命名的空struct Lambda 和 function 指針實際上完全不同。 使用 function 指針,要執行的代碼僅在運行時才知道,位於指針后面。 使用 lambda,要執行的代碼在編譯時是已知的,而 lambda object 實際上是閉包,捕獲變量的集合。 在這里,沒有這樣的變量,所以 lambdas 不需要存儲任何東西。

無捕獲的 lambda 不需要任何子對象; 它只是一種具有operator()重載的類型。 因此,它可以是(但不是必須是)空類型。 unqiue_ptr被允許(但不是必需的)優化它“包含”刪除器類型的方式,這樣,如果刪除器類型是空的 class 類型,那么它可以使用各種技術來確保該類型不占用存儲空間unique_ptr實例本身。

有幾種方法可以做到這一點。 unique_ptr可以從類型繼承,依靠 EBO 優化掉基礎 class。 使用 C++20,它可以將其作為成員子對象,依靠[[no_unique_address]]屬性來提供空成員優化。 無論哪種情況, unique_ptr<T>需要的唯一實際存儲是指向T的指針。

相比之下,function 指針是 function 指針。 它是必須具有存儲的基本類型,因為它可以指向具有該簽名的任何 function。 一個類型本質上包含成員 function 作為類型本身的一部分來調用; function 指針沒有。 該類型的實例實際上並不需要存儲來找到它的operator()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM