Gre*_*Cat 6 c++ shared-ptr unique-ptr
我想知道是否有任何合理的理由在C++中通过引用返回唯一指针,即std::unique_ptr<T>&?
我以前从来没有真正看过这个技巧,但是我得到的新项目似乎很多都使用这个模式.从第一眼看,它只是有效地打破/规避了"独特的所有权"合同,使得无法在编译时捕获错误.请考虑以下示例:
class TmContainer {
public:
TmContainer() {
// Create some sort of complex object on heap and store unique pointer to it
m_time = std::unique_ptr<tm>(new tm());
// Store something meaningful in its fields
m_time->tm_year = 42;
}
std::unique_ptr<tm>& time() { return m_time; }
private:
std::unique_ptr<tm> m_time;
};
auto one = new TmContainer();
auto& myTime = one->time();
std::cout << myTime->tm_year; // works, outputs 42
delete one;
std::cout << myTime->tm_year; // obviously fails in the runtime, as `one` is deleted
Run Code Online (Sandbox Code Playgroud)
请注意,如果我们只返回std::unique_ptr<tm>(不是引用),则会引发明确的编译时错误,或强制使用移动语义:
// Compile-time error
std::unique_ptr<tm> time() { return m_time; }
// Works as expected, but m_time is no longer owned by the container
std::unique_ptr<tm> time() { return std::move(m_time); }
Run Code Online (Sandbox Code Playgroud)
我怀疑一般的经验法则是所有这些案件都值得使用std::shared_ptr.我对吗?
这有两个用例,在我看来,这表明设计不佳。拥有非常量引用意味着您可以窃取或替换资源,而无需提供单独的方法。
// Just create a handle to the managed object
auto& tm_ptr = tm_container.time();
do_something_to_tm(*tm_ptr);
// Steal the resource
std::unique_ptr<TmContainer> other_tm_ptr = std::move(tm_ptr);
// Replace the managed object with another one
tm_ptr = std::make_unique<TmContainer>;
Run Code Online (Sandbox Code Playgroud)
我强烈反对这些做法,因为它们容易出错且可读性较差。最好提供如下所示的界面,前提是您确实需要此功能。
tm& time() { return *m_time; }
std::unique_ptr<tm> release_time() { return {std::move(m_time)}; }
// If tm is cheap to move
void set_time(tm t) { m_time = make_unique<tm>(std::move(t)); }
// If tm is not cheap to move or not moveable at all
void set_time(std::unique_ptr t_ptr) { m_time = std::move(t_ptr); }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1955 次 |
| 最近记录: |