【问题标题】:Is such assignment a good idea in C++在 C++ 中这样的赋值是个好主意吗
【发布时间】:2013-04-02 16:15:06
【问题描述】:

很多类的赋值运算符 (operator=) 与析构函数中的代码相同,但与复制构造函数的代码非常相似。

那么以这种方式实现分配是个好主意吗?

Point& operator=(const Point& point)
{
    if(&point != this)
    {
        //Call the destructor
        this->~Point();

        //Make the placement new
        //Assignment is made because some compilers optimise such code as just
        //  new Point;
        Point* p_n = new (this) Point(point);

        //We where placing in this place so pointers should be equal
        assert(p_n == this);
    }
    return *this;
}

【问题讨论】:

  • 如果你这样做,一定要先检查&point != this
  • 另外,这段代码也不是异常安全的——如果new (this) Point(point) 出现异常,将会造成双重破坏。只需使用copy and swap idiom。
  • 新展示位置能否引发异常?
  • @Seagull,Point 的 ctor(或正在构造的类型)可以抛出。
  • @Seagull,“我确信从构造函数中抛出是一件可怕的事情” - 从 构造函数 中抛出是一件很棒的事情!它允许建立对象不变量和use it easily

标签: c++ new-operator variable-assignment placement-new


【解决方案1】:

没有。这是一个坏主意,即使 C++ 标准在讨论对象生命周期时使用这种东西作为示例。对于像Point 这样的值类型还不错,但是如果你从这个类派生,这个赋值实现会将对象的类型从你的派生类型更改为Point;如果涉及虚函数,您会看到行为发生巨大变化。

【讨论】:

  • 在这种情况下,赋值和复制构造函数都应该被禁止。如果存在,我的方法使用复制构造函数。可能我没听懂你。
  • @Seagull - 我认为你的意思是实现赋值运算符。以这种方式实现它为此类用户设置了一个陷阱,结果是致命的。试试看!
【解决方案2】:

Herb Sutterone of his GotW articles 中解决了这个问题。我建议你阅读它。他的结论:

原来的成语充满了陷阱,经常是错误的,它使 对于派生类的作者来说,生活简直就是地狱。我有时 很想把上面的代码贴在办公室厨房里,并附上标题: “这里是龙。”

来自 GotW 编码标准:

  • 如有必要,更喜欢编写一个通用的私有函数来在复制和复制分配之间共享代码;永远不要使用 通过使用 显式析构函数后跟放置新,即使这个技巧 新闻组每三个月出现一次(即,永远不要写:

    T& T::operator=( const T& other )
    {
        if( this != &other)
        {
            this->~T();             // evil
            new (this) T( other );  // evil
        }
        return *this;
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多