使用无分配交换有明显的缺点吗?

问题描述

| 我正在实现(出于培训目的)冒泡排序模板功能:
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的副本构造函数,我可以看到异常安全问题。但是,如果允许赋值运算符抛出,则标准版本中存在相同的问题。 这里的问题是,您能看到此版本的交换中可能存在的缺点吗? 干杯     

解决方法

        不同之处在于,当赋值运算符失败时,您仍然拥有相同数量的对象。 如果您破坏一个对象而未能创建一个新对象,则一个对象将丢失!如果它是容器的一部分,则容器的状态可能也无效。     ,        除此之外,如果一个类没有赋值运算符,则其设计者可能不打算将其交换。如果这样做,他们也可能也禁用了复制构造,因此您的新交换功能仍然无法使用。 关于您声称标准库容器不需要分配的主张-是正确的,只要您不想实际对它们做任何有用的事情即可。该代码是否为您编译?
#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
}
我认为不会。     ,        您需要一个复制ctor而不是一个赋值运算符,但是两者非常相似,至少在典型情况下,您将同时拥有或没有。 IOW,我认为这通常不会完成很多事情。 我会在xor交换技巧的旁边进行分类:有趣,但通常没用。     ,        这可能会使将来的代码维护者感到困惑。     

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...