簡體   English   中英

通過C ++ 11 lambda中的引用捕獲靜態變量

[英]Capturing a static variable by reference in a C++11 lambda

主要問題

我正在嘗試使用GCC 4.7.2編譯以下代碼:

#include <iostream>

int foo() {
    static int bar;
    return [&bar] () { return bar++; } (); // lambda capturing by reference
}

int main (int argc, char* argv[]) {
    std::cout << foo() << std::endl;
    return 0;
}

似乎進展不順利,因為輸出是這樣的:

$p2.cpp: In function ‘int foo()’:
$p2.cpp:6:14: warning: capture of variable ‘bar’ with non-automatic storage duration [enabled by default]
$p2.cpp:4:16: note: ‘int bar’ declared here

所以,我的第一個問題是:

這是GCC的失敗,還是代碼不合法​​C ++ 11? 這在GCC的最新版本中是否已修復?

在shared_ptr工廠中使用技巧

我考慮使用非文字靜態變量構建基於此原理的工件。 此工件旨在成為shared_ptr <T>對象的工廠,當您只需要為同一實例使用重復的shared_ptr容器時,它可以避免創建新的T對象。

這個工件看起來像:

std::shared_ptr<Foo> create(std::string name) {
    static std::unordered_map<std::string,std::weak_ptr<Foo>> registry;

    if (auto it = registry.find(name) != registry.end())
        return registry[name].lock();

    auto b = std::shared_ptr<Foo>(
        new Foo(name), 
        [&registry] (Foo* p) {
            registry.erase(p->getName());
            delete p;
        });

    registry.emplace(name,b);
    return b;
}

據我所知,如果之前討論的GCC問題在C ++ 11一致性方面不是問題,那么這個工件也不應該成為問題。 使用此hack唯一要注意的是,不要將生成的shared_ptr <T>對象設置為可以在靜態變量之后被破壞的任何全局對象。

我這是對的嗎?

為什么你甚至試圖捕捉bar 這是靜態的。 您根本不需要捕獲它。 只需要捕獲自動變量。 Clang會對您的代碼產生嚴重錯誤,而不僅僅是警告。 如果你只是從lambda捕獲中刪除&bar ,那么代碼就能完美運行。

#include <iostream>

int foo() {
    static int bar;
    return [] () { return bar++; } (); // lambda capturing by reference
}

int main (int argc, char* argv[]) {
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    return 0;
}

版畫

0
1
2

按照標准,你只能捕捉自動存儲時間(或變量this ,這是因為明確提到可拍攝)。

所以,不,你不能按照標准這樣做(或者,回答你的第一個問題,那不是有效的C ++ 11而不是編譯器錯誤)

5.1.1 / 2 lambda-capture中的名稱應在lambda表達式的上下文中,並且應為此或引用具有自動存儲持續時間的局部變量或引用。

編輯:而且,正如Kevin所說,你甚至不需要捕獲本地static

暫無
暫無

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

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