此問題是"Constructor with by-value parameter & noexcept"的對偶。這個問題表明,值函數參數的生命週期管理由調用函數處理;因此,調用者處理髮生的任何異常,被調用函數可以標記爲noexcept
。我想知道如何處理輸出結果noexcept
。按值返回功能並且不接受
MyType MyFunction(SomeType const &x) noexcept;
//...
void MyCaller()
{
MyType test1 = MyFunction(RandomSomeType());
MyType test2{ MyFunction(RandomSomeType()) };
//...
test1 = MyFunction(RandomSomeType());
test2 = std::move(MyFunction(RandomSomeType()));
MyFunction(RandomSomeType()); // return value goes to oblivion
}
假設在MyFunction
內成功創建了返回值。假設MyType
的適當特殊成員函數(複製/移動分配/構造)可能不是是noexcept
。
- 執行RVO/NRVO /無論從 - C++關於返回值從調用的函數給調用者轉移11條規則意味着轉移總是成功的沒有拋出不管的的
noexcept
狀態適當的特殊成員功能? - 如果對上一個問題的答案是「否」,那麼如果返回值傳輸拋出,則針對被調用的函數或調用者計數異常嗎?
- 如果上一個問題的答案是「被調用函數」,那麼
MyFunction
上的普通noexcept
標記將導致調用std::terminate
。應該將MyFunction
的noexcept
配置文件更改爲?當我在Usenet上詢問這個問題時,被訪者認爲它應該是std::is_nothrow_move_assignable<MyType>::value
。 (請注意,MyCaller
使用了幾種使用返回值的方法,但MyFunction
將不知道哪一個正在使用!答案必須涵蓋所有情況。)如果MyType
更改爲可複製但不可移動?
因此,如果第二和第三個問題最糟糕的情況是準確的,那麼按值返回任何函數不能有一個簡單的noexcept
如果返回類型有一個界外球能夠感動!現在使用可拋出移動的類型應該很少見,但是每次使用按值返回時,模板代碼仍然必須使用is_nothrow_move_assignable
「自己弄髒」。
我覺得做被叫功能負責被打破:
MyType MyFunction(SomeType const &x) noexcept(???)
{
//...
try {
return SOME_EXPRESSION;
// What happens if the creation of SOME_EXPRESSION succeeds, but the
// move-assignment (or whatever) transferring the result fails? Is
// this try/catch triggered? Or is there no place lexically this
// function can block a throwing move!?
} catch (...) {
return MyType();
// Note that even if default-construction doesn't throw, the
// move-assignment may throw (again)! Now what?
}
}
這個問題,至少對我來說,似乎是在調用者的結束可以解決的(只是包裝與布展分配的try
/catch
),但從被調用函數的末尾不可修復。我認爲調用者必須處理這個問題,即使我們需要改變C++規則來做到這一點。或者至少需要某種缺陷報告。
糾正我,如果我錯了,但RVO/NRVO /移動優化不影響誰構建對象,只有它構建的內存。你的對象將直接在調用者(通常是調用者的棧)提供的內存位置構造,但構造函數調用本身將位於被調用者的棧幀內。所以,如果構造函數拋出,它將被調用者「拋出」它。 – lapk 2012-02-14 06:22:32
對不起,我的意思是「在被調用者的代碼段內」,而不是「在被調用者的棧幀內」。 – lapk 2012-02-14 07:31:50