雖然今天重構一些代碼以將原始指針更改爲std::unique_ptr
,但由於order of evaluation錯誤,我遇到了分段錯誤。C++ 17表達式評估順序和std :: move
舊的代碼不喜歡的東西如下:
void add(const std::string& name, Foo* f)
{
_foo_map[name] = f;
}
void process(Foo* f)
{
add(f->name, f);
}
代碼的第一,天真,重構使用std::unique_ptr
:
void add(const std::string& name, std::unique_ptr<Foo> f)
{
_foo_map[name] = std::move(f);
}
void process(std::unique_ptr<Foo> f)
{
add(f->name, std::move(f)); // segmentation-fault on f->name
}
重構後的代碼會導致分段錯誤,因爲第二個參數(std::move(f)
)首先被處理,然後第一個參數(f->name
)將一個移動的變量取消引用,繁榮!
可以修復這個是獲得一個手柄上Foo::name
之前在呼叫移動它add
:
void process(std::unique_ptr<Foo> f)
{
const std::string& name = f->name;
add(name, std::move(f));
}
或許:
void process(std::unique_ptr<Foo> f)
{
Foo* fp = f.get();
add(fp->name, std::move(f));
}
這些解決方案都需要額外的行的代碼,並且看起來幾乎不像原來的(雖然UB)調用add
。
問題:
要麼是上面慣用 C++的2個提出的解決方案,如果沒有,有沒有更好的選擇?
由於P0145R3 - Refining Expression Evaluation Order for Idiomatic C++,我看到C++ 17有變化。這是否會改變上述解決方案/防止他們的陷阱?
我會說一個「慣用」的解決方案是重構'add'函數,或者添加一個需要'std :: unique_ptr'對象的重載。 –
@Someprogrammerdude只是將需求從'process'轉移到'add'的權限上,但是對嗎?或者P0145R3解決這個問題? –
國際海事組織通常是一個好主意,儘可能將這些細節推向最下面。畢竟抽象是OO和C++的主要部分之一。 –