C++ C++;0x move构造函数明白了

C++ C++;0x move构造函数明白了,c++,c++11,move-constructor,C++,C++11,Move Constructor,编辑:我在这里再次问了同样的问题(在解决了这个问题所指出的问题之后): 基本思想是,如果你不小心,指向可移动的东西可能会得到一些奇怪的结果 < > C++移动构造函数和移动赋值操作符看起来是非常积极的事情。它们可以在复制构造函数毫无意义的情况下使用,因为它们不需要指向重复的资源 但有些情况下,如果你不小心,它们会咬你。这一点尤其重要,因为我已经看到了允许编译器生成move构造函数的默认实现的建议。如果有人能给我一个这样的链接,我会提供 因此,这里有一些代码有一些可能不完全明显的缺陷。我测试了代

编辑:我在这里再次问了同样的问题(在解决了这个问题所指出的问题之后):

基本思想是,如果你不小心,指向可移动的东西可能会得到一些奇怪的结果


< > C++移动构造函数和移动赋值操作符看起来是非常积极的事情。它们可以在复制构造函数毫无意义的情况下使用,因为它们不需要指向重复的资源

但有些情况下,如果你不小心,它们会咬你。这一点尤其重要,因为我已经看到了允许编译器生成move构造函数的默认实现的建议。如果有人能给我一个这样的链接,我会提供

因此,这里有一些代码有一些可能不完全明显的缺陷。我测试了代码,以确保它在带有
-std=gnuc++0x
标志的g++中编译。这些缺陷是什么?您将如何修复它们

#if (__cplusplus <= 199711L) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
   #error This requires c++0x
#endif

#include <unordered_set>
#include <vector>
#include <utility>
#include <algorithm>

class ObserverInterface {
 public:
   virtual ~ObserverInterface() {}

   virtual void observedChanged() = 0;
   virtual void observedGoingAway() = 0;
};

class Observed {
 private:
   typedef ::std::unordered_set<ObserverInterface *> obcontainer_t;

 public:
   Observed() {}
   Observed(const Observed &) = delete;
   const Observed &operator =(const Observed &b) = delete;
   // g++ does not currently support defaulting the move constructor.
   Observed(Observed &&b) : observers_(::std::move(b.observers_)) { }
   // g++ does not currently support defaulting move assignment.
   const Observed &operator =(Observed &&b) {
      observers_ = ::std::move(b.observers_);
      return *this;
   }
   virtual ~Observed() {
      for (auto i(observers_.begin()); i != observers_.end(); ++i) {
         (*i)->observedGoingAway();
      }
   }

   void unObserve(ObserverInterface *v) {
      auto loc(observers_.find(v));
      if (loc != observers_.end()) {
         observers_.erase(loc);
      }
   }

   void changed() {
      if (!observers_.empty()) {
         // Copy observers_ to bector so unObserve works
         ::std::vector<ObserverInterface *> tmp;
         tmp.reserve(observers_.size());
         tmp.assign(observers_.begin(), observers_.end());

         for (auto i(tmp.begin()); i != tmp.end(); ++i) {
            (*i)->observedChanged();
         }
      }
   }

 private:
   obcontainer_t observers_;
};

class Observer : public ObserverInterface {
 public:
   Observer() {}
   Observer(const Observer &) = delete;
   const Observer &operator =(const Observer &b) = delete;
   // g++ does not currently support defaulting the move constructor.
   Observer(Observer &&b) : observed_(b.observed_) {
      b.observed_ = 0;
      return *this;
   }
   // g++ does not currently support defaulting move assignment.
   const Observer &operator =(Observer &&b) {
      observed_ = b.observed_;
      b.observed_ = 0;
      return *this;
   }
   virtual ~Observer() {
      if (observed_) {
         observed_->unObserve(this);
         observed_ = 0;
      }
   }

   virtual void observedChanged() {
      doStuffWith(observed_);
   }
   virtual void observedGoingAway() {
      observed_ = 0;
   }

 private:
   Observed *observed_;

   // Defined elsewhere
   void doStuffWith(Observed *);
};
#如果(uu cplusplus observedgoingway();
}
}
void unObserve(observer接口*v){
自动定位(查找(v));
如果(loc!=observators_uu.end()){
删除(loc);
}
}
作废已更改(){
如果(!obsers.empty()){
//将观察员抄送给bector,以便不受影响地工作
:std::向量tmp;
tmp.reserve(观察者大小());
tmp.assign(观察者\开始(),观察者\结束());
for(自动i(tmp.begin());i!=tmp.end();+i){
(*i)->观察到的变化();
}
}
}
私人:
观察者;
};
类观察者:公共观察者接口{
公众:
观察者(){}
观察者(const Observer&)=删除;
常量观察者和运算符=(常量观察者和b)=删除;
//g++当前不支持默认移动构造函数。
观察者(观察者和b):观察者(b.观察者){
b、 观察值=0;
归还*这个;
}
//g++当前不支持默认移动分配。
常量观察者和运算符=(观察者和运算符){
观察到的;
b、 观察值=0;
归还*这个;
}
虚拟观察者(){
如果(观察到){
观察到的(这个);
观察值=0;
}
}
观察到的虚拟无效已更改(){
多斯塔夫韦(观察到);
}
虚拟void observedgoingway(){
观察值=0;
}
私人:
观察到的*观察到的;
//在别处定义
空隙度(观察*);
};

代码有很多问题

  • observator::observed\uuz
    在默认构造函数中保持未初始化状态,从而在调用析构函数时导致未定义的行为
  • 除了0之外,没有任何值被分配给
    观察者::观察者
    ,这使得变量多余
  • 即使有办法将观察者与被观察者关联,移动观察者时也不会进行注册
  • 您试图从观察者的移动构造函数返回一个值
  • 已经解决了你想解决的任何问题
  • 从赋值运算符返回非常量引用更为惯用

  • 代码有很多问题

  • observator::observed\uuz
    在默认构造函数中保持未初始化状态,从而在调用析构函数时导致未定义的行为
  • 除了0之外,没有任何值被分配给
    观察者::观察者
    ,这使得变量多余
  • 即使有办法将观察者与被观察者关联,移动观察者时也不会进行注册
  • 您试图从观察者的移动构造函数返回一个值
  • 已经解决了你想解决的任何问题
  • 从赋值运算符返回非常量引用更为惯用

  • 这是测验吗?你知道缺陷是什么吗?没有“正确的”回答,因为这需要讨论。更好的社区Wiki it,如果你想让它有机会不被关闭…@Greg Hewgill,我知道缺陷是什么。我注意到有几个人问他们知道答案的问题,因为他们认为这些问题的答案在网站上会很有用,很有教育意义.这就是这样一个问题。@Omnifarious:对于这样一个“我知道答案,你知道吗?”这类问题要想有用,就必须足够具体,让能够从中学习的人能够真正找到它。目前这类问题太开放了。如果你想回答别人还没有问过的问题,那么就把问题具体化,让想问的人能够找到它。@jalf,这是有道理的。我投了赞成票结束这个问题,我将修改它,并以不同的方式提问。这是一个测验吗?你知道缺陷是什么吗?没有“正确的”回答,因为这需要讨论。更好的社区Wiki it,如果你想让它有机会不被关闭…@Greg Hewgill,我知道缺陷是什么。我注意到有几个人问他们知道答案的问题,因为他们认为这些问题的答案在网站上会很有用,很有教育意义.这就是这样一个问题。@Omnifarious:对于这样一个“我知道答案,你知道吗?”这类问题要想有用,就必须足够具体,让能够从中学习的人能够真正找到它。目前这类问题太开放了。如果你想回答别人还没有问过的问题,那么就把问题具体化,让想问的人能够找到它。@jalf,这是有道理的。我投了赞成票关闭此问题,我将修改它并以不同的方式提问。叹气谢谢。您已经强调了与我所想的内容无关的足够多的问题,我认为我应该删除此问题并重新开始。不过,您有我所想的问题之一。#3.叹气谢谢。您已经强调了与我所想的内容无关的足够多的问题我对t的想法感到惊讶