在這個代碼示例中,我們將 a 傳遞std::shared_ptr<int>給一個執行緒,并期望它被弱化為 a std::weak_ptr<int>。但是在 Visual Studio 2019 中,t在除錯和發布版本中,該程式的輸出為“pw alive”。linux 上的編譯器也有同樣的問題g -lpthread。
這個玩具示例的動機是更嚴重的情況,執行緒進行t一些長時間的計算,然后通過共享資源發送結果t作為引數接收。這些資源可能在t的計算程序中被其他執行緒洗掉,在這種情況下t變得無用并且可以提前終止。但是由于這個(疑似)錯誤,t使資源保持活動狀態并浪費記憶體和計算時間。
這真的是一個錯誤,還是我誤解了weak_ptr和之間的關系shared_ptr?如果這是一個錯誤,您知道在哪里報告嗎?Visual Studio 和 g 可能在不同的地方。
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
void TestWeakPtrAlive(std::weak_ptr<int> pw)
{
// wait for main thread to delete pw
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<int> p = pw.lock();
std::cout << (p ? "pw alive" : "pw dead")
<< std::endl;
}
int main()
{
std::shared_ptr<int> p = std::make_shared<int>(18);
std::thread t(TestWeakPtrAlive, p);
p = nullptr;
t.join();
return 0;
}
uj5u.com熱心網友回復:
這些實作復制了shared_ptr. 即他們復制引數并將其系結到執行緒的生命周期。復制是帶有執行緒創建的引數系結的默認設定。
這不會被視為錯誤,除非標準說實作不能這樣做。
至于獲得您想要的行為,我認為如果您使用 lambda,您會遇到同樣的問題。相反,您可以使用函子,或者您可以使用一些全域或靜態變數。
這是您轉換為使用函子的示例。好處是您可以控制成員變數。缺點是樣板。
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
class TestWeakPtrAlive
{
std::weak_ptr<int> m_pw;
public:
TestWeakPtrAlive(std::weak_ptr<int> pw)
: m_pw(std::move(pw))
{}
void operator()()
{
// wait for main thread to delete pw
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<int> p = m_pw.lock();
std::cout << (p ? "pw alive" : "pw dead")
<< std::endl;
}
};
int main()
{
std::shared_ptr<int> p = std::make_shared<int>(18);
auto functor = TestWeakPtrAlive(p);
std::thread t(std::move(functor));
p = nullptr;
t.join();
return 0;
}
編輯:我只是想到了一個相當明顯的解決方案,即創建一個 weak_ptr 并將其傳遞給執行緒建構式。
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
void TestWeakPtrAlive(std::weak_ptr<int> pw)
{
// wait for main thread to delete pw
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<int> p = pw.lock();
std::cout << (p ? "pw alive" : "pw dead")
<< std::endl;
}
int main()
{
std::shared_ptr<int> p = std::make_shared<int>(18);
std::weak_ptr<int> wp = p;
std::thread t(TestWeakPtrAlive, std::move(wp));
p = nullptr;
t.join();
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/354211.html
