C ++ 11智能指针用例

时间:2014-04-16 09:14:43

标签: c++ c++11 smart-pointers

假设我正在开发一个小型电影数据库。在像python这样的动态语言中,我写道:

db = ConnectionFactory.get_connection(db_name) # (1) Create database connection
model = MovieModel(db)                         # (2) object-to-relational mapper
star_wars = Movie("Star Wars", ...)
model.store(star_wars)                         # (3) Save object
et = model.fetch("E.T.")                       # (4) Retrieve one object
movies = model.fetch_all()                     # (5) Retrieve all objects

当将它转换为C ++时,问题就出现了如何传递对象:通过值,引用,普通指针或一些智能指针之一。

第1行包含一个Abstract Factory,它返回某个基类的子类,因此这里需要返回一个指针。问题是,应该返回什么样的指针? std::unique_ptr似乎很合适。

在第2行构造MovieModel,它将数据库连接作为参数并存储以供将来使用。由于一个连接可以在一个或多个模型之间共享,因此数据库连接应该传递并存储为std::shared_ptr,我猜想。但是,我应该将std::unique_ptr创建的ConnectionFactory转换为shared_ptr还是修改ConnectionFactory以返回shared_ptr

在第3行中,一个对象存储在数据库中。由于Movie很简单"数据" class,它应该通过const引用传递值,或者更好。这很简单,但在第4行检索另一个对象。由于Movie具有"值"语义,按值返回似乎很自然。但是当找不到特定的电影时会发生什么?抛出异常或将返回类型更改为智能指针并在这种情况下返回nullptr是否更好?

最后,返回一组对象。返回容器(例如std::vector)对象或(智能)指针容器是否更好?在后一种情况下,哪些指针?

3 个答案:

答案 0 :(得分:3)

案例1 + 2:我认为最初由shared_ptr返回是有意义的,因为数据库连接本身似乎是“可共享的”#34;在这个设计中。这样,Case2解决了问题。

案例3:通过const引用传递Movie。如果Movie是一个类似值的类(并且没有任何昂贵的复制句柄),那么带有const-ref参数的简单单个版本的store应该可以并保持代码简单。

如果您需要建模&#34;未找到&#34;在fetch方法中,使用boost::optional<Movie>(或类似的东西)作为返回值。

案例最后:对于Movie,使用按值排序的集合(std::vector<Movie>)。 (在C ++ 11中,无论如何都会移动返回的向量。)

答案 1 :(得分:2)

  

db = ConnectionFactory.get_connection(db_name)#(1)创建数据库   连接

谁拥有db?当它被摧毁?

  1. 这个堆栈拥有它并且应该在最后被销毁=&gt;使用std::unique_ptr
  2. 这是保存在类(例如MovieManager)成员中,只要所有其他对象=&gt;类就会存在。使用std::unique_ptr并将原始指针传递给其他对象
  3. db可能比此堆栈和类更长,并与其他对象共享=&gt; std::shared_ptr
  4. 请注意,在上述所有情况下,工厂应返回unique_ptr,除非它返回现有的共享连接,如果是shared_ptrunique_ptr可以自动升级到shared_ptr

      

    model = MovieModel(db)#(2)   对象 - 关系映射器

    1. 如果db是std :: unique_ptr,并且您希望MoviewModel从现在开始拥有所有权,std::move(db)
    2. 模型将在此堆栈中销毁,通过db.get()
    3. 模型需要共享所有权,因为最后可能销毁任何模型,传递为shared_ptr
    4. star_wars = Movie("Star Wars", ...) 
      model.store(star_wars)    # (3) Save object
      

      两个选项:

      1. const Movie&Movie&&
      2. 重叠商店
      3. 让商店按价值拍摄电影
      4. 如果您不想在此功能中再次使用star_wars,请致电std::move(star_wars)

          

        et = model.fetch(&#34; E.T。&#34;)#(4)检索一个   对象

        作为异常或optional<Movie>

        的对象
          

        movies = model.fetch_all()#(5)全部检索   对象

        std::vector<Movie>

答案 2 :(得分:1)

编辑:我在这里说了一些不那么聪明的东西,完全忽略了标题中的C ++ 11。

关于3和5的一些个人观点:

3)我想不出有什么理由在这里使用value而不是const引用。至少只要存储不会以某种非常不寻常的方式发生。

最后一点:我总是更喜欢指针容器,以最大限度地减少内存周围的随机复制。在C ++ 11中,您可以使用unique_ptr或shared_ptr,具体取决于它们以后的用途。