按引用存储shared_ptr还是按值存储?

Storing shared_ptr by reference vs by value?

提问人: 提问时间:6/26/2020 更新时间:6/26/2020 访问量:113

问:

如果我的班级有:Zoo

std::vector<std::shared_ptr<Animal>> table;

while 是其他人继承的抽象类。Animal

我想实现一个函数,该函数将动物插入到表中(不是动物的副本,而是动物本身)

所以我写道:

void Game::addAnimal(int location, shared_ptr<Animal> animal) {
    table[location] = animal;
}
  1. 我写对了吗?

  2. 如果我想保存该动物的新副本,我该怎么做? 如果在 c'tor 中我初始化大小为 = 10 的表,如下所示:

C++ 继承 按引用 值传递

评论

0赞 6/26/2020
解决了这个问题,所以我的代码是正确的吗?
0赞 Eljay 6/26/2020
只要表的大小使其已经具有位置索引(很难知道,因为省略了代码的那部分),是的,这看起来是正确的。问题标题与代码不符。此代码不按引用存储shared_ptr,而是按值存储shared_ptr。
0赞 6/26/2020
会解决这个问题,我的第二个问题呢,如果我想,我该如何保存副本(不需要它,但想知道:-))。
0赞 user4581301 6/26/2020
注意:按值传递会复制 和 导致与参数 的不必要(且可能代价高昂)的所有权共享。智能编译器可能能够看到发生了什么并消除副本,但如果通过引用传递,则不会有问题。shared_ptr<Animal> animalshared_ptranimalanimal
1赞 Eljay 6/26/2020
应该尽量只有一个问题。你的 Animal 类将需要一个虚拟克隆方法,因此你可以通过调用 clone 显式创建副本,派生类可以执行正确的操作。

答:

0赞 PiotrK 6/26/2020 #1

首先认为shared_ptr绝对是一个指针,尽管语法糖。

所以如果你写:

void Game::addAnimal(int location, shared_ptr<Animal> animal)
{
   table[location] = animal;
}

将指向 animal 的指针存储在 中。如果调用函数 addAnimal 10 次,则将获得 10 个指向单个且相同的动物的指针。例如,如果你改变了,那么你实际上已经改变了原来的动物,所以 - 例如 - 也将等于 4。table[location]table[2]->legs = 4table[7]->legs

如果你想使用 animal 的副本,那么你需要提供 copy 构造函数。请注意,复制对象比仅复制指向对象的指针要慢得多。

从智能指针复制看起来像从普通指针复制:

shared_ptr<Animal> animal = getAnimal();
Animal animal2 = *animal; // Make a copy, or:
shared_ptr<Animal> animal3 = std::make_shared<Animal>(*animal); // invoke copy constructor.

在上述情况下,所有三种动物都是不同的对象,因此如果您更改其中一种,其他动物将保持不变。

请记住,您仍然需要复制构造函数才能正常工作。