class PrettyMenu {
...
std::tr1::shared_ptr<Image> bgImage;
...
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
Lock ml(&mutex);
bgImage.reset(new Image(imgSrc));
++imageChanges;
}
如果Image构造函数抛出异常,有可能输入流input stream的读取记号read marker已被移走,而这样的搬移对程序其余部分是一种可见的状态改变。这个我可以理解,但是后面说可以通过copy and swap达到高级“异常安全”的策略
struct PMImpl { // PMImpl = "PrettyMenuImpl
std::tr1::shared_ptr<Image> bgImage;
int imageChanges;
};
class PrettyMenu {
...
private:
Mutex mutex;
std::tr1::shared_ptr<PMImpl> pImpl;
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
using std::swap; // see Item 25
Lock ml(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc));
++pNew->imageChanges;
swap(pImpl, pNew);
}
}
【1】我不明白copy and swap为什么就可以解决上述问题。pNew->bgImage.reset(new Image(imgSrc))还是要读取istream,而且如果image构造函数抛出异常,上述的问题还是存在呀?而且之前的代码也可以在image构造不成功的情况下不调用reset,为什么还要多此一举呢?
【2】还有为什么要把bgImage与imageChanges放在struct PMImpl中,为什么不直接把这两个变量放在PrettyMenu中?