在下面的代碼中,物件被相同型別的新物件覆寫,其中 lambda 運算式創建了一個使用this舊物件的閉包。舊地址 ( this) 保持不變,新物件具有相同的布局,所以這應該沒問題而不是 UB。但是非平凡的物件或其他情況呢?
struct A {
void g(A& o, int v) {
o = A{.x = v, .f = [this]{
std::cout << "f" << this->x << '\n';
}};
}
int x{0};
std::function<void()> f;
~A() {
std::cout << "dtor" << x << '\n';
}
};
void test() {
A a;
a.g(a, 2);
a.f();
}
uj5u.com熱心網友回復:
您實際上并沒有替換任何物件。您只是將另一個物件分配給當前物件。o = 只需呼叫隱式復制賦值運算子,該運算子將從A賦值運算式中構造的臨時成員中復制分配各個成員A{...}。
lambdathis將從thisin中捕獲g,而不是從臨時物件中捕獲。
std::function將始終保留 lambda 的副本,該副本參考g被呼叫的原始物件,并且由于這是其父物件,因此它不能活得更長。
所以這里沒有問題。唯一的例外是您在物件f銷毀期間呼叫A,在這種情況下,可能會禁止使用捕獲的指標。
uj5u.com熱心網友回復:
這是一個帶有角落案例的稍微修改的代碼。我在一個函式中創建一個臨時物件并呼叫g它,并傳遞一個更永久的物件。臨時消失,長壽命物件現在有一個閉包,在其生命結束后參考一個物件。呼叫f是UB:
#include <iostream>
#include <functional>
struct A {
void g(A& o, int v) {
o = A{ .x = v, .f = [this] {
std::cout << "f" << this->x << ' ' << this << '\n';
} };
}
int x{ 0 };
std::function<void()> f;
~A() {
std::cout << "dtor" << x << ' ' << this << '\n';
}
};
void test(A& a) {
A b{ 2 };
b.g(a, 3);
}
int main() {
A a{ 1 };
std::cout << a.x << '\n';
test(a);
std::cout << a.x << '\n';
a.f(); // UB because a.f uses an object after its end of life
}
輸出是:
1
dtor3 0135F9C0
dtor2 0135FA30
3
f341072 0135FA30
dtor3 0135FAA8
證明呼叫a.f()試圖使用地址 0135FA30 的物件(在該特定運行中)在它被銷毀后。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/437744.html
