Я видел много вопросов и ответов относительно идиомы копирования и обмена (в сочетании с идиомой pimpl). Недавно я реализовал класс, используя оба, и в итоге получил несколько вопросов:
1 В случае класса с прыщами, нужна ли мне (по-прежнему) функция, не являющаяся другом swap
(как описано в этот вопрос )? Поскольку вопрос уже 10 лет, есть ли какие-либо изменения в этом отношении?
2 В случае pimpl (основанного на уникальном ptr), стандартная std::swap
не будет работать нормально? (В этом случае мне не нужен пользовательский своп)
3 У меня есть все члены в структуре pimpl. Если все копируемое, разве я не могу использовать конструктор копирования по умолчанию?
// trial.h
class Trial
{
public:
Trial(ID a_ID = UNKNOWN_ID);
Trial(const Trial& rhs);
Trial(Trial&& rhs) noexcept;
~Trial();
Trial& operator=(Trial rhs);
void swap(Trial& rhs);
inline ID GetID() const;
private:
struct TrialImpl;
std::unique_ptr<TrialImpl> m_Impl;
};
// trial.cpp
struct Trial::TrialImpl
{
TrialImpl(ID a_ID) :
m_ID(a_ID){}
TrialImpl(const TrialImpl& rhs)
{
// make a deep copy (perhaps use default copy constructor)
m_ID = rhs.m_ID;
m_Frames = rhs.m_Frames;
}
ID m_ID;
std::vector<Frame> m_Frames;
};
Trial::Trial(ID a_ID) :
m_Impl(std::make_unique<TrialImpl>(a_ID))
{
}
Trial::Trial(const Trial& rhs) :
m_Impl(std::make_unique<TrialImpl>(*rhs.m_Impl))
{
}
Trial::Trial(Trial&&) noexcept = default;
Trial::~Trial() = default;
Trial& Trial::operator=(Trial rhs)
{
swap(rhs);
return *this;
}
void Trial::swap(Trial& rhs)
{
// we can just let std::swap swap the unique pointers
std::swap(m_Impl, rhs.m_Impl);
}
ID Trial::GetID() const
{
return m_Impl->m_ID;
}