我正在实施(用于培训目的)冒泡排序模板功能:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
当我意识到这个函数不能用于没有赋值运算符的类时,就像这个(请原谅我的坏名字):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
编译器引发此错误错误1错误C2248:'NoCopyable :: operator =':无法访问类'NoCopyable'中声明的私有成员
所以,我稍微修改代码使用而不是std :: swap函数我的交换函数版本,这里是代码:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
代码编译并给出正确的结果。但是我不完全确定,我记得Sutter的文章建议你避免玩物体的生活时间。这篇文章只是通过玩火而不实际给你任何真正的理由来警告你。如果T1或T2的拷贝构造函数可以抛出,我可以在异常安全中看到问题。但是,如果允许赋值运算符抛出,则标准版本中存在相同的问题。
在这个问题中,你能看到这个版本的交换存在任何可能的缺点吗?
干杯
答案 0 :(得分:8)
除了其他任何东西,如果一个类没有赋值运算符,它的设计者可能不打算交换它。如果他们这样做了,他们也可能禁用了复制结构,所以你的新交换功能仍然无效。
关于标准库容器不需要赋值的断言 - 只要您不想对它们实际执行任何有用的操作,这是正确的。这段代码是否为你编译?
#include <vector>
using namespace std;
struct A {
private:
void operator=( const A &);
};
int main() {
vector <A> v;
v.push_back( A() );
v[0] = A(); // assignment needed here
}
我认为不会。
答案 1 :(得分:6)
不同之处在于,当赋值运算符失败时,您仍然拥有相同数量的对象。
如果您销毁一个对象并且无法创建新对象,则会丢失一个对象!如果它是容器的一部分,容器的状态可能也是无效的。
答案 2 :(得分:4)
你需要一个副本ctor而不是一个赋值运算符,但这两者非常相似,至少在一个典型的情况下,你会有两者,或者你都没有。我不认为这通常可以实现很多。
我将它与xor-swap技巧一起排序:有趣,但通常没用。
答案 3 :(得分:3)
未来的代码维护者可能会感到困惑。