【问题标题】:What is the correct way to pass a std::vector to be a parameter?将 std::vector 作为参数传递的正确方法是什么?
【发布时间】:2017-01-04 06:56:31
【问题描述】:

我想传递一个填充了基于对象的同一类的向量。 std::reference_wrapper 和 no-reference 都不能修复它。 解决这个问题的正确方法是什么?

class MyClass
{
public:
    MyClass(int){};
    virtual void print() const {
        std::cout<<"MyClass"<<std::endl;
    }
};
class MySubClass : public MyClass
{
public:
    MySubClass(int a):MyClass(a){};
    virtual void print() const {
        std::cout<<"MySubClass"<<std::endl;
    }
};
void test(const std::vector<std::reference_wrapper<MyClass>>& v)
{
    for (const auto& c : v) {
        c.get().print();
    }
}
void test(const std::vector<MyClass>& v)
{
    for (const auto& c : v) {
        c.print();
    }
}
int main() 
{
    {
        MySubClass s(2);
        std::vector<MyClass> v;
        v.push_back(s);
        test(v);//print MyClass, but I need MySubClass
    }
    {
        MySubClass s(2);
        std::vector<std::reference_wrapper<MyClass>> v;
        v.push_back(s);
        test(v);//print MySubClass
        test({2});
        test({s});//wrong ambigious
    }
    return 0;
}

【问题讨论】:

  • const std::vector&lt;MyClass&gt;&amp; v - 这里没有MyClass 的副本,因为您传递的是对向量的引用。
  • 您将苹果与摩托车进行比较——您想要引用向量还是对象向量?它们有完全不同的用途。你想做什么?
  • @Holt 抱歉,我说得不够清楚。现在我重新编辑了。
  • @ChrisDodd 抱歉,我说得不够清楚。现在我重新编辑了。

标签: c++ c++11 vector stl reference-wrapper


【解决方案1】:
{
    MySubClass s(2);
    std::vector<MyClass> v;
    v.push_back(s);
    test(v);//print MyClass, but I need MySubClass
}

这里的问题是您试图将MySubClass 对象存储在MyClass 的向量中。不可能存储整个MySubClass,而是只存储MyClass 父子对象。这与您将存储的对象视为MySubClass 实例的愿望相冲突。

{
    MySubClass s(2);
    std::vector<std::reference_wrapper<MyClass>> v;
    v.push_back(s);

这解决了前面的问题。引用可以引用其静态类型的子类。不过,请记住,对象并未存储在向量中。该对象存储为局部变量s,并且仅由向量引用。

    test(v);//print MySubClass
    test({2});
    test({s});//wrong ambigious

这里的问题是你有两个重载,它们都不接受MySubClass,但都接受可以从MySubClass 的初始化列表中初始化的东西。因此,重载决议是不明确的。编译器不知道您打算调用哪个重载。

要么使用显式临时初始化而不是普通的初始化列表。

    test(std::vector<MyClass>{2});
    test(std::vector<std::reference_wrapper<MyClass>>{s});

或者不使用重载,而是使用唯一命名的函数。

void test(const std::vector<std::reference_wrapper<MyClass>>& v)
void test2(const std::vector<MyClass>& v)

【讨论】:

  • OP 可能还想考虑std::vector&lt;const MyClass*&gt;。它的行为与 reference_wrapper 版本非常相似,但对于代码的读者来说可能在概念上更简单。
  • @MartinBonner 但是,指针可能会丢失test({2}) 这个方便的语法。
  • @Ringo_D:对。如果该语法对您有用,那么指针就不那么有吸引力了。 (对于许多应用程序来说,它不会。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2015-09-20
  • 1970-01-01
  • 2016-06-07
  • 2021-03-26
  • 2020-05-14
相关资源
最近更新 更多