【问题标题】:error: no matching function for call to 'std::vector<Pet*>::vector(<brace-enclosed initializer list>)'错误:没有匹配函数调用 'std::vector<Pet*>::vector(<brace-enclosed initializer list>)'
【发布时间】:2019-11-19 03:49:09
【问题描述】:

您好,我需要帮助解决 C++ 的此错误。 我正在尝试创建一个返回包含宠物对象的向量的函数。 我尝试使用 pushback,仍然无法编译。 我还有一堆其他类(猫、狗、鱼等)也继承了宠物基类。

这是我的功能的一个片段。

std::vector<Pet*> make_pets() {

    //why doesn't this work?
std::vector<Pet*> newVector {Cat(), Dog()};
   return newVector;
//newVector.push_back(c);


}

【问题讨论】:

  • Cat()Pet,而不是 Pet*。您的目标可能是new Cat(),但最好将vector 更改为std::vector&lt;std::unique_ptr&lt;Pet&gt; 并将Cat() 更改为std::make_unique&lt;Cat&gt;()unique_ptr 将安全地为您处理内存管理。
  • 您好,我按照您所说的做了,当我尝试返回我的 newVector 时出现错误 - 错误:无法从 'std::vector<:unique_ptr> >' 到 'std::vector' 代码:std::vector<:unique_ptr>> newVector; newVector.push_back(std::make_unique ());返回新向量;
  • 类型必须始终保持不变。如果你返回一个``std::vector<:unique_ptr>>, the variable receiving it needs to be a std::vector<:unique_ptr>>`

标签: c++ class inheritance


【解决方案1】:

OPs 代码中的错误:

std::vector<Pet*> newVector {Cat(), Dog()};

Cat() 创建Cat 的临时实例。类型为Cat(或Cat&amp;)。 std::vector&lt;Pet*&gt; 的元素类型是 Pet*,这是不兼容的。应用地址运算符 (&amp;Cat()) 会使事情变得更糟。虽然现在类型会匹配(如果Cat 派生自Pet,则可以将Cat* 分配给Pet*),Cat() 会创建一个 临时 实例。它没有提供足够的生命周期,因为它会在表达式结束时自动销毁,这会在 std::vector 中留下一个悬空指针。

要解决这个问题,可以使用new

std::vector<Pet*> newVector {new Cat(), new Dog()};

大肠杆菌上的 MCVE:

#include <iostream>
#include <memory>
#include <vector>

struct Pet {
  virtual ~Pet() = default;
  virtual const char* what() const = 0;
};

struct Cat: public Pet {
  virtual const char* what() const override { return "cat"; }
};

struct Dog: public Pet {
  virtual const char* what() const override { return "dog"; }
};

std::vector<Pet*> make_pets()
{
  std::vector<std::unique_ptr<Pet>> vec{ new Cat(), new Dog() };
  return vec;
}

int main()
{
  std::vector<std::unique_ptr<Pet>> pets = make_pets();
  std::cout << "Pets:\n";
  for (const Pet *pPet : pets) std::cout << pPet->what() << '\n';
  for (const Pet *pPet : pets) delete pPet;
}

输出:

Pets:
cat
dog

Live Demo on coliru

使用new 创建实例会导致必须使用delete 显式销毁这些实例。只是清除 std::vector&lt;Pet*&gt; pets 会导致实例未被删除并丢失——内存泄漏。


std::unique_ptr(由@user4581301 推荐)的用法有点棘手。因为std::unique_ptr 的实例是唯一拥有/持有指针的实例,所以它可能不会被复制或分配,而只是移动。经过一番摆弄,我得到了一个关于 coliru 的 mcve:

#include <iostream>
#include <memory>
#include <vector>

struct Pet {
  virtual ~Pet() = default;
  virtual const char* what() const = 0;
};

struct Cat: public Pet {
  virtual const char* what() const override { return "cat"; }
};

struct Dog: public Pet {
  virtual const char* what() const override { return "dog"; }
};

std::vector<std::unique_ptr<Pet>> make_pets()
{
  std::vector<std::unique_ptr<Pet>> vec;
  vec.emplace_back(std::make_unique<Cat>());
  vec.emplace_back(std::make_unique<Dog>());
  return vec;
}

int main()
{
  std::vector<std::unique_ptr<Pet>> pets = make_pets();
  std::cout << "Pets:\n";
  for (const std::unique_ptr<Pet> &pPet : pets) std::cout << pPet->what() << '\n';
}

输出:

Pets:
cat
dog

Live Demo on coliru

在这种情况下,Pet 实例的销毁不是问题。 std::unique_ptr&lt;Pet&gt; 允许指针本身被删除后立即删除。

【讨论】:

    猜你喜欢
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多