Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我在GotW#28中遗漏了什么:快速Pimpl习语?_C++ - Fatal编程技术网

C++ 我在GotW#28中遗漏了什么:快速Pimpl习语?

C++ 我在GotW#28中遗漏了什么:快速Pimpl习语?,c++,C++,“这是赫伯·萨特写的一篇老文章。在那篇文章中,Herb解释了为什么下面的设计是个坏主意(尽管我冒昧地用静态断言替换了断言): 假设Y类既没有基类也没有其他成员,我想说Y::operator=(const Y&)和Y:~Y()的异常保证将是相应的X::operator=(const X&)和X:~X()的异常保证。但是赫伯·萨特暗示说还有更多的麻烦 我遗漏了什么?我不能谈论异常安全问题,但这种方法的一个缺点是,如果您需要更改sizeofx,那么SizeOfy也可能会更改,这意味着任何使用类Y的二进

“这是赫伯·萨特写的一篇老文章。在那篇文章中,Herb解释了为什么下面的设计是个坏主意(尽管我冒昧地用
静态断言
替换了
断言
):

假设
Y
类既没有基类也没有其他成员,我想说
Y::operator=(const Y&)
Y:~Y()
的异常保证将是相应的
X::operator=(const X&)
X:~X()
的异常保证。但是赫伯·萨特暗示说还有更多的麻烦


我遗漏了什么?

我不能谈论异常安全问题,但这种方法的一个缺点是,如果您需要更改
sizeofx
,那么
SizeOfy
也可能会更改,这意味着任何使用
类Y
的二进制文件都需要重新编译,才能正确使用新的
类Y
。这消除了Pimpl的一个优点,即能够修改类的内部实现,而不必强制重新生成引用/使用该类的所有代码。请尝试编写(定义)一个
Y::operator=()
,假设
X::operator=()
可能引发异常。另外,虽然std::aligned_storage并不存在,但类型对齐是一个重要的考虑因素,并且所示的代码会破坏这一点。@Peter,我做到了。这是问题中的第二个代码片段。如果
X::operator=()
抛出异常,它将按原样通过
Y::operator=()
并到达客户机代码。对不起,我还是看不出有什么问题。你能解释一下吗?您是否假设
Y::operator=()
应该是
noexcept
?在我看来不应该。抛出的赋值运算符在我看来非常正常。@JeremyFriesner,你说得对:公开实现类的大小会引入生成依赖项。但这对我来说不是问题。事实上,我需要客户端代码知道类的内存占用,并在每次更改时重新编译。@IgorG-您假设
Y::operator=()
是全部或全无-它要么成功,要么不抛出,要么抛出,否则没有效果。考虑如果需要提供一个强异常保证和<代码> y>代码>包含了必须分配的多个成员,以及第一个可以抛出的那些任务中的任何一个。
// file y.h
class Y
{
    /*...*/
    static const size_t sizeofx = /*some value*/;
    char x_[sizeofx];
};

// file y.cpp
#include "x.h"

Y::Y() {
    static_assert( sizeofx >= sizeof(X), "Please, fix Y::sizeofx" );
    new (&x_[0]) X;
}

Y::~Y()
{
    (reinterpret_cast<X*>(&x_[0]))->~X();
}
Y& Y::operator=(const Y& other)
{
    *reinterpret_cast<X*>(&x_[0]) = *reinterpret_cast<const X*>(&other.x_[0]);
    return *this;
}