在复制和交换方式中实现交换
以下是什么是复制和交换习语以及如何为我的课程提供交换功能,我尝试实现交换功能,就像后面接受的答案选项2(具有调用成员函数的自由函数)而不是直接友好免费功能在前面的链接。
但以下内容不能编译
#include <iostream>
// Uncommenting the following two lines won't change the state of affairs
// class Bar;
// void swap(Bar &, Bar &);
class Bar {
public:
Bar(unsigned int bottles=0) : bottles(bottles) { enforce(); } // (1)
Bar(Bar const & b) : bottles(b.bottles) { enforce(); } // (1)
Bar & operator=(Bar const & b) {
// bottles = b.bottles;
// enforce();
// Copy and swap idiom (maybe overkill in this example)
Bar tmp(b); // but apart from resource management it allows (1)
// to enforce a constraint on the internal state
swap(*this, tmp); // Can't see the swap non-member function (2)
return *this;
}
void swap(Bar & that) {
using std::swap;
swap(bottles, that.bottles);
}
friend std::ostream & operator<<(std::ostream & out, Bar const & b) {
out << b.bottles << " bottles";
return out;
}
private:
unsigned int bottles;
void enforce() { bottles /=2; bottles *= 2; } // (1) -- Ensure the number of bottles is even
};
void swap(Bar & man, Bar & woman) { // (2)
man.swap(woman);
}
int main () {
Bar man (5);
Bar woman;
std::cout << "Before -> m: " << man << " / w: " << woman << std::endl;
swap(man, woman);
std::cout << "After -> m: " << man << " / w: " << woman << std::endl;
return 0;
}
我知道复制和交换习语在这里是过度的,但它也允许通过复制构造函数(1)强制对内部状态施加一些约束(更具体的例子是维持一个缩减形式的分数)。 不幸的是,这不会编译,因为编译器看到的(2)的唯一候选者是Bar :: swap成员函数。 我坚持与朋友非成员函数方法?
编辑:去我的答案下面,看看我最后感谢所有关于这个问题的答案和评论。
我认为我们发布c ++ 11?
在这种情况下,std :: swap的默认实现将是最优的,只要我们正确地实现move-assignment操作符和move-constructor(理想情况下不会)
http://en.cppreference.com/w/cpp/algorithm/swap
#include <iostream>
class Bar {
public:
Bar(unsigned int bottles=0) : bottles(bottles) { enforce(); } // (1)
Bar(Bar const & b) : bottles(b.bottles) {
// b has already been enforced. is enforce necessary here?
enforce();
} // (1)
Bar(Bar&& b) noexcept
: bottles(std::move(b.bottles))
{
// no need to enforce() because b will have already been enforced;
}
Bar& operator=(Bar&& b) noexcept
{
auto tmp = std::move(b);
swap(tmp);
return *this;
}
Bar & operator=(Bar const & b)
{
Bar tmp(b); // but apart from resource management it allows (1)
swap(tmp);
return *this;
}
void swap(Bar & that) noexcept {
using std::swap;
swap(bottles, that.bottles);
}
friend std::ostream & operator<<(std::ostream & out, Bar const & b) {
out << b.bottles << " bottles";
return out;
}
private:
unsigned int bottles;
void enforce() { } // (1)
};
/* not needed anymore
void swap(Bar & man, Bar & woman) { // (2)
man.swap(woman);
}
*/
int main () {
Bar man (5);
Bar woman;
std::cout << "Before -> m: " << man << " / w: " << woman << std::endl;
using std::swap;
swap(man, woman);
std::cout << "After -> m: " << man << " / w: " << woman << std::endl;
return 0;
}
预期结果:
Before -> m: 5 bottles / w: 0 bottles
After -> m: 0 bottles / w: 5 bottles
编辑:
对于任何关注表演的人(例如@JosephThompson)的帮助,我都可以减轻你的担忧。 移动呼叫后std::swap
到一个虚函数(强制铛生产的所有任意代码),然后与苹果铛编译具有-02,这样的:
void doit(Bar& l, Bar& r) override {
std::swap(l, r);
}
成为这样:
__ZN8swapper24doitER3BarS1_: ## @_ZN8swapper24doitER3BarS1_
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp85:
.cfi_def_cfa_offset 16
Ltmp86:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp87:
.cfi_def_cfa_register %rbp
movl (%rsi), %eax
movl (%rdx), %ecx
movl %ecx, (%rsi)
movl %eax, (%rdx)
popq %rbp
retq
.cfi_endproc
看到? 最佳。 C ++标准库很有用!
注意:这是使用复制和交换的pre C ++ 11方法。 对于C ++ 11解决方案,请参阅此答案
为了得到这个工作,你需要修复一些事情。 首先,您需要转发声明swap swap函数,以便operator=
知道它。 为了做到这一点,您还需要转发declare Bar
以便swap
名称为bar的类型
class Bar;
void swap(Bar & man, Bar & woman);
// rest of code
然后我们需要告诉编译器在哪里寻找swap
。 我们这样做的方式是使用范围解析运算符。 这将告诉编译器在类的外部范围内查找swap
函数
Bar & operator=(Bar const & b) {
// bottles = b.bottles;
// enforce();
// Copy and swap idiom (maybe overkill in this example)
Bar tmp(b); // but apart from resource management it allows (1)
// to enforce a constraint on the internal state
::swap(*this, tmp); // Can't see the swap non-member function (2)
//^^ scope operator
return *this;
}
我们把所有这些放在一起,我们得到这个实例
真的,但复制operator =
应该看起来像
Bar & operator=(Bar b) // makes copy
{
::swap(*this, b) // swap the copy
return *this; // return the new value
}
你知道Bar
有一个swap
成员函数,所以直接调用它。
Bar& operator=(Bar const& b) {
Bar tmp(b);
tmp.swap(*this);
return *this;
}
非成员swap
仅存在,以便Bar
客户端可以利用其优化的swap
实现而不知道它是否存在,使用using std::swap
idiom启用参数相关查找:
using std::swap;
swap(a, b);
链接地址: http://www.djcxy.com/p/72937.html
上一篇: Implementing the swap in the copy and swap idiom
下一篇: how do I call an inline friend function with the same name as a member function?