只是面对一种情况,不知道该怎么办...这是我现在拥有的代码:

class IMyDbAccessor {
 public:
  int getSum();  // quite important for my case that it is not const.
                 // it does some caching. Of course I may use mutable,
                 // but actually it is not that important here.
};

void SomeBusinessLogic(IMyDbAccessor& dbacc) { /* implementation */ }

int main(int argc, char** argv) {
    MyDbAccessor acc(argv);
    SomeBusinessLogic(acc);
}


我不喜欢它,因为它的表现力不足。我想拥有

void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ }


表示SomeBusinessLogic想要拥有一个传递的对象,因此main应该看起来像

int main(int argc, char** argv) {
    MyDbAccessor acc(argv);
    SomeBusinessLogic(std::move(acc));
}


但是,当然这是不可能的……没有人知道这是什么原因吗?对我来说,这是完全合理的。

还是我的感觉是错误的,我不应该让SomeBusinessLogic负责IMyDbAccessor的所有权,所以最好将它作为const IMyDbAccessor&传递?

最佳答案

我不喜欢它,因为它的表现力不足。


看起来很能表达我的意思。通过引用传递对象意味着该功能可以对调用方提供的现有对象进行操作,而不是对副本进行操作。不用担心管理所有权。


  我想拥有

void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ }

  
  表示SomeBusinessLogic想要拥有一个传递的对象


那不是右值引用所代表的。右值引用意味着dbacc将引用由编译器在实际调用站点处创建的临时对象,或调用方通过std::move()传递的预先存在的对象。无论哪种方式,都希望在dbacc退出后不再使用SomeBusinessLogic()所引用的对象,因此允许SomeBuinessLogic()“窃取” dbacc所引用的对象所拥有的任何内部数据的所有权,而不是复制它。这与对象本身的所有权无关。这仍然严格取决于调用方。


  所以main应该看起来像

int main(int argc, char** argv) {
    MyDbAccessor acc(argv);
    SomeBusinessLogic(std::move(acc));
}

  
  但是当然不可能...


您要查找的是std::unique_ptr

void SomeBusinessLogic(std:::unique_ptr<IMyDbAccessor> dbacc) { /* implementation */ }

int main(int argc, char** argv) {
    std::unique_ptr<IMyDbAccessor> acc(new MyDbAccessor(argv));
    SomeBusinessLogic(std::move(acc));
}


要么:

int main(int argc, char** argv) {
    SomeBusinessLogic(std::make_unique<MyDbAccessor>(argv));
}


一次只能有一个std::unique_ptr持有给定的指针,因为std::unique_ptr销毁时释放所指向的内存。那就是使它“独特”的原因。看到std::unique_ptr时,您知道所有者是谁。将std::unique_ptr对象按值传递给函数意味着它仅在函数的生存期内存在。

因此,这种方法非常清楚地表明,dbacc本身而不是调用方拥有IMyDbAccessor对象的专有所有权,并且在SomeBusinessLogic()退出时将释放该对象(除非SomeBusinessLogic()决定选择std::move()dbacc之外的另一个std::unique_ptr)。


  还是我的感觉是错误的,我不应该让SomeBusinessLogic()负责SomeBusinessLogic的所有权,所以最好将它作为IMyDbAccessor传递?


我会的,是的。除非出于某些令人信服的理由,const IMyDbAccessor&必须将所有权从调用者手中夺走。

关于c++ - C++中的虚拟 move 构造函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47232340/

10-11 17:43