从boost library documentation我读到了这个:
 Â从概念上讲,智能指针被视为拥有指å‘的对象, Â Â å› æ¤åœ¨ä¸å†å˜åœ¨æ—¶è´Ÿè´£åˆ 除对象   需è¦çš„。
我有一个éžå¸¸ç®€å•çš„问题:我想使用RAII作为å¯å¤åˆ¶å’Œå¯åˆ†é…类的指针属性。
å¤åˆ¶å’Œèµ‹å€¼æ“作应该很深:æ¯ä¸ªå¯¹è±¡éƒ½åº”该有自己的实际数æ®å‰¯æœ¬ã€‚æ¤å¤–,RTTI需è¦å¯ç”¨äºŽå±žæ€§ï¼ˆå®ƒä»¬çš„类型也å¯ä»¥åœ¨è¿è¡Œæ—¶ç¡®å®šï¼‰ã€‚
我应该æœç´¢å¯å¤åˆ¶æ™ºèƒ½æŒ‡é’ˆçš„实现(数æ®å¾ˆå°ï¼Œæ‰€ä»¥æˆ‘ä¸éœ€è¦Copy on Write指针),或者我将å¤åˆ¶æ“ä½œå§”æ‰˜ç»™æˆ‘çš„å¯¹è±¡çš„å‰¯æœ¬æž„é€ å‡½æ•°æ˜¾ç¤ºåœ¨this answer?
我å¯ä»¥é€‰æ‹©å“ªç§æ™ºèƒ½æŒ‡é’ˆç”¨äºŽå¯å¤åˆ¶å’Œå¯åˆ†é…的类的简å•RAII? (我认为带有委托å¤åˆ¶/赋值æ“作的unique_ptr到类å¤åˆ¶æž„é€ å‡½æ•°å’Œèµ‹å€¼è¿ç®—符会åšå‡ºæ£ç¡®çš„选择,但我ä¸ç¡®å®šï¼‰
这是使用原始指针的问题的伪代ç ,它åªæ˜¯ä¸€ä¸ªé—®é¢˜æ述,而ä¸æ˜¯æ£åœ¨è¿è¡Œçš„C ++代ç :
// Operation interface
class ModelOperation
{
public:
virtual void operate = ();
};
// Implementation of an operation called Special
class SpecialModelOperation
:
public ModelOperation
{
private:
// Private attributes are present here in a real implementation.
public:
// Implement operation
void operate () {};
};
// All operations conform to ModelOperation interface
// These are possible operation names:
// class MoreSpecialOperation;
// class DifferentOperation;
// Concrete model with different operations
class MyModel
{
private:
ModelOperation* firstOperation_;
ModelOperation* secondOperation_;
public:
MyModel()
:
firstOperation_(0),
secondOperation_(0)
{
// Forgetting about run-time type definition from input files here.
firstOperation_ = new MoreSpecialOperation();
secondOperation_ = new DifferentOperation();
}
void operate()
{
firstOperation_->operate();
secondOperation_->operate();
}
~MyModel()
{
delete firstOperation_;
firstOperation_ = 0;
delete secondOperation_;
secondOperation_ = 0;
}
};
int main()
{
MyModel modelOne;
// Some internal scope
{
// I want modelTwo to have its own set of copied, not referenced
// operations, and at the same time I need RAII to for the operations,
// deleting them automatically as soon as it goes out of scope.
// This saves me from writing destructors for different concrete models.
MyModel modelTwo (modelOne);
}
return 0;
}
ç”案 0 :(得分:5)
如果您接å—对类型的æŸäº›è¦æ±‚,则å¯ä»¥åœ¨ä¸éœ€è¦ä¸ºæ‰€æœ‰ç±»åž‹å®žçŽ°è™šæ‹Ÿå…‹éš†åŠŸèƒ½çš„情况下完æˆæ¤æ“作。特殊è¦æ±‚是类型具有å¯è®¿é—®çš„æ‹·è´æž„é€ å™¨ï¼Œç”±äºŽå¯èƒ½çš„æ„å¤–åˆ‡ç‰‡ï¼Œä¸€äº›äººè®¤ä¸ºè¿™äº›æž„é€ å™¨æ˜¯ä¸åˆéœ€è¦çš„。但是,æ£ç¡®ä½¿ç”¨å‹æƒ…å¯ä»¥å‡è½»è¿™ç§ç¼ºç‚¹ã€‚
如果å¯ä»¥æŽ¥å—,å¯ä»¥é€šè¿‡åœ¨æä¾›å¤åˆ¶åŠŸèƒ½çš„ç•Œé¢ä¸‹åˆ 除派生类型æ¥è§£å†³æ¤é—®é¢˜ï¼š
template <typename Base>
struct clonable {
// virtual copy
// this clone function will be generated via templates
// no boilerplate is involved
virtual std::unique_ptr<clonable<Base>> clone() const = 0;
// expose the actual data
virtual Base* get() = 0;
virtual Base const* get() const = 0;
// virtual destructor
// note that this also obviates the need for a virtual destructor on Base
// I would probably still make it virtual, though, just in case
virtual ~clonable() = default;
};
æ¤æŽ¥å£ç”±æœ€è¡ç”Ÿç±»åž‹æ¨¡æ¿åŒ–çš„ç±»å®žçŽ°ï¼Œå› æ¤çŸ¥é“如何通过å¤åˆ¶æž„é€ å‡½æ•°åˆ¶ä½œæ£å¸¸å‰¯æœ¬ã€‚
template <typename Base, typename Derived>
struct clonable_holder : clonable<Base> {
// I suppose other constructors could be provided
// like a forwarding one for emplacing, but I am going for minimal here
clonable_holder(Derived value)
: storage(std::move(value)) {}
// here we know the most derived type, so we can use the copy constructor
// without risk of slicing
std::unique_ptr<clonable<Base>> clone() const override {
return std::unique_ptr<clonable<Base>>(new clonable_holder(storage));
}
Base* get() override { return &storage; }
Base const* get() const override { return &storage; }
private:
Derived storage;
};
这将为我们生æˆè™šæ‹Ÿå¤åˆ¶åŠŸèƒ½ï¼Œè€Œæ— 需é¢å¤–çš„æ ·æ¿ã€‚现在我们å¯ä»¥åœ¨æ¤åŸºç¡€ä¸Šæž„建一个类似智能指针的类(ä¸æ˜¯ä¸€ä¸ªæ™ºèƒ½æŒ‡é’ˆï¼Œå› 为它ä¸æ供指针è¯ä¹‰ï¼Œè€Œæ˜¯æ供值è¯ä¹‰ï¼‰ã€‚
template <typename Base>
struct polymorphic_value {
// this constructor captures the most derived type and erases it
// this is a point where slicing may still occur
// so making it explicit may be desirable
// we could force constructions through a forwarding factory class for extra safety
template <typename Derived>
polymorphic_value(Derived value)
: handle(new clonable_holder<Base, Derived>(std::move(value))) {
static_assert(std::is_base_of<Base, Derived>::value,
"value must be derived from Base");
}
// moving is free thanks to unique_ptr
polymorphic_value(polymorphic_value&&) = default;
polymorphic_value& operator=(polymorphic_value&&) = default;
// copying uses our virtual interface
polymorphic_value(polymorphic_value const& that)
: handle(that.handle->clone()) {}
polymorphic_value& operator=(polymorphic_value const& that) {
handle = that.handle->clone();
return *this;
}
// other useful constructors involve upcasting and so on
// and then useful stuff for actually using the value
Base* operator->() { return handle.get(); }
Base const* operator->() const { return handle.get(); }
// ...
private:
std::unique_ptr<clonable<Base>> handle;
};
è¿™åªæ˜¯ä¸€ä¸ªæœ€å°çš„ç•Œé¢ï¼Œä½†å®ƒå¯ä»¥å¾ˆå®¹æ˜“地从这里充实,以涵盖更多的使用场景。
ç”案 1 :(得分:4)
现在有点晚了,但对于未æ¥çš„观众:在我的仅é™æ ‡é¢˜çš„资æºåº“AuroraåŠå…¶SmartPtr tutorialä¸æœ‰ä¸€ä¸ªçŽ°æˆçš„实施方å¼ã€‚使用Aurora,通过智能指针实现深层拷è´æ˜¯å¾®ä¸è¶³é“的。以下代ç 适用于任何å¯å¤åˆ¶ç±»åž‹(car 1)
:
T
如果您的类具有指针æˆå‘˜ï¼Œåˆ™é€šå¸¸ä¸å¿…实现The Big Three / Five。
ç”案 2 :(得分:1)
我从未å¬è¯´è¿‡çŽ°æˆçš„å®žçŽ°ï¼Œä½†ä½ å¯ä»¥è‡ªå·±åŠ¨æ‰‹åšã€‚
é¦–å…ˆä½ åº”è¯¥å†™ä¸€äº›æ¨¡æ¿åŒ…装类,它有虚拟克隆方法,返回å˜å‚¨å¯¹è±¡çš„副本。然åŽå†™ä¸€äº›å¯å¤åˆ¶çš„类的多æ€æŒæœ‰è€…
并且ä¸è¦å¿˜è®°æ£€æŸ¥åˆ 除 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Checked_delete
ç”案 3 :(得分:1)
å¬èµ·æ¥éœ€è¦èƒ½å¤Ÿåˆ›å»ºä¸€ä¸ªæ™ºèƒ½æŒ‡é’ˆï¼Œæ¯æ¬¡åˆ›å»ºå¦ä¸€ä¸ªæ™ºèƒ½æŒ‡é’ˆå¯¹è±¡æ—¶éƒ½ä¼šåˆ›å»ºå¯¹è±¡çš„新副本。 (我认为,该副本是å¦â€œæ·±åº¦â€å–å†³äºŽå¯¹è±¡çš„æž„é€ å‡½æ•°;对于我们所知é“的所有,您å˜å‚¨çš„对象å¯èƒ½å…·æœ‰å¾ˆå¤šå±‚次的所有æƒï¼Œå› æ¤â€œæ·±åº¦â€å–决于对象的å«ä¹‰å¯¹è±¡ã€‚我们的目的主è¦æ˜¯ä½ 想è¦ä¸€ä¸ªåˆ›å»ºä¸€ä¸ªç‹¬ç‰¹å¯¹è±¡çš„东西,当智能指针使用å¦ä¸€ä¸ªå¼•ç”¨æž„建时,而ä¸æ˜¯åªå–出一个指å‘现有对象的指针。)
如果我已æ£ç¡®ç†è§£äº†è¿™ä¸ªé—®é¢˜ï¼Œé‚£ä¹ˆæ‚¨å°†éœ€è¦ä¸€ä¸ªè™šæ‹Ÿå…‹éš†æ–¹æ³•ã€‚没有其他方法å¯ä»¥æ£ç¡®è°ƒç”¨æ´¾ç”Ÿç±»çš„æž„é€ å‡½æ•°ã€‚
struct Clonable {
virtual ~Clonable() {}
virtual Clonable* clone() = 0;
};
struct AutoPtrClonable {
AutoPtrClonable(Clonable* cl=0) : obj(cl) { }
AutoPtrClonable(const AutoPtrClonable& apc) : obj(apc.obj->clone()) { }
~AutoPtrClonable() { delete obj; }
// operator->, operator*, etc
Clonable* obj;
};
使用示例代ç ,将其转æ¢ä¸ºæ¨¡æ¿ç‰
ç”案 4 :(得分:0)
ä½ æœ‰ä¸¤ä¸ªè§£å†³æ–¹æ¡ˆï¼ˆå®žé™…ä¸Šä½ æœ‰æ›´å¤šï¼Œä½†è¿™äº›å¯¹æˆ‘æ¥è¯´æœ€æœ‰æ„义:)):
首先,您å¯ä»¥ä½¿ç”¨std::unique_ptr
ã€‚è¿™æ˜¯ä¸€ä¸ªå¾ˆå¥½çš„è§£å†³æ–¹æ¡ˆï¼Œå› ä¸ºå®ƒä¼šå¼ºåˆ¶æ¯ä¸ªæŒ‡é’ˆæœ‰ä¸€ä¸ªå®žä¾‹ã€‚ (使用std::shared_ptr
代替也å¯ä»¥ï¼Œä½†å¦‚æžœä½ æ²¡æœ‰æ˜Žç¡®åœ°æ·»åŠ ä»£ç ,shared_ptrçš„å¤åˆ¶å’Œåˆ†é…将“共享†- ç‰¹åˆ«æ˜¯ä½ æƒ³é¿å…的。)
如果使用std::unique_ptr
,则å¤åˆ¶æž„é€ å‡½æ•°å’Œèµ‹å€¼è¿ç®—符应显å¼æ·±å±‚å¤åˆ¶ï¼ˆä½¿ç”¨æŒ‡é’ˆå¯¹è±¡æŽ¥å£ä¸çš„虚拟clone
方法,或者调用{{1}ä¸çš„æ–°è¿ç®—ç¬¦æž„é€ å‡½æ•°ï¼‰ã€‚
å…¶æ¬¡ï¼Œä½ å¯ä»¥è‡ªå·±åŠ¨æ‰‹ã€‚它并没有什么å¤æ‚的,我们谈论的是一个å°åž‹ï¼ˆ10-20行左å³ï¼‰çš„实用程åºç±»ã€‚
就个人而言,如果我必须在一个地方使用这个智能指针类,我会使用std :: unique_ptr。å¦åˆ™ï¼ˆå¤šæŒ‡é’ˆï¼Œç›¸åŒçš„è¡Œä¸ºï¼‰æˆ‘ä¼šè‡ªå·±æ»šåŠ¨ï¼Œå› æ¤æˆ‘ä¸å¿…为许多实例é‡å¤æ·±å±‚å¤åˆ¶ï¼ˆä»¥ä¿æŒDRY原则)。