【问题标题】:How to Add Element into a std::vector using std::any如何使用 std::any 将元素添加到 std::vector
【发布时间】:2022-01-19 16:07:01
【问题描述】:

我正在开发一个 C++17 项目,我正在使用 std::any。下面给出了一个最小的可重现示例,以供参考,解释我想要实现的目标。

#include <any>
#include <vector>
#include <iostream>
int main()
{
    std::vector<int> vec{1,2,3};
    
    std::any anything = vec;
    
   // anything.push_back(4);//i want to add an element into vector vec, using variable anything but this statement won't work

    
    std::cout<<std::any_cast<std::vector<int>>(anything).size()<<std::endl;//prints 3 
    std::any_cast<std::vector<int>>(anything).push_back(4);//this adds(push_back) element into rvalue
    std::cout<<std::any_cast<std::vector<int>>(anything).size()<<std::endl;//prints 3 but i want 4 
}

从上面的例子可以看出,我有一个std::any 对象,我正在使用std::any_cast 将元素添加到向量中。我想将元素添加到名为 vec 的实际 (lvalue) 向量中,但是将元素添加到 rvalue 中。 有没有办法使用std::any 将元素添加到名为vec 的向量中。 如果没有,那么还有其他方法可以做到这一点,例如使用std::variant 或其他我可能不会的方法意识到。我正在寻找一种在任何版本的 C++(如 C++11 或 C++17 等)中执行此操作的方法。

在我的实际项目中,需要存储任何类型的对象。所以我在那里遇到了同样的问题。然后意识到出了什么问题(即,我们在右值上使用了push_back),然后我将问题简化为一个最小的可重现示例并在这里询问。

【问题讨论】:

  • 你为什么使用std::any?以及为什么要包装(实际上是复制)现有的vector
  • 在我的实际项目中,需要存储任何类型的对象。所以我在那里遇到了同样的问题。然后意识到出了什么问题(即,我们在右值上使用push_back)然后我将问题简化为一个最小的可重现示例并在这里询问。
  • 没关系,但为什么还要访问旧的vector
  • 在我看来这不是一个很棒的设计。也许您应该考虑重构您的项目?
  • 澄清一下,您是想将元素添加到向量vec,还是从vec 复制构造的anything 中存储的向量?您可以互换使用这两者,但它们不是同一个对象。

标签: c++ c++11 c++17 stdany


【解决方案1】:

你错过了一个参考:

std::any_cast<std::vector<int>&>(anything).push_back(4);
//                            ^

目前,您使用std::any_cast 创建副本。

注意: 正如 Nicol Bolas 所指出的,这只是避免为演员表复制,但不会避免将初始 std::vector 复制到 std::any 中。

【讨论】:

  • 这将为您提供对 any 中的对象的引用,但不是对 vec 的引用。
  • 提问者的代码中似乎没有任何地方他们认为他们引用了vec,但事实并非如此。将副本复制到anything 后,所有后续代码都作用于anything,并且没有任何作用于vec
  • @NicolBolas:确实,但不确定它是否不足以满足 OP。
  • @NathanPierson:“在提问者的代码中似乎没有任何地方他们认为他们正在引用 vec 但不是。” OP 特别指出,“有没有办法使用 std::any 将元素添加到名为 vec 的向量中”。它甚至是粗体字。 OP 显然不知道 any 默认不引用原始对象。
  • @NicolBolas 哦,是的,我的错。
【解决方案2】:

我们在右值上使用 push_back

不,这不是问题所在。 any 存储其所提供内容的副本。它不引用其他对象。它根据给定的内容创建一个对象。因此,即使您在 any 中获得对对象的引用,它也不会是对 vec 本身的引用。

如果您想在 any 中存储对对象的引用,则需要通过存储指向该对象的指针或 reference_wrapper 来明确地这样做:

using ref_type = decltype(std::ref(vec));

std::any anything = std::ref(vec);

std::any_cast<ref_type>(anything).get().push_back(4);

请注意,拥有引用对象的any 是危险的。如果any 的生命周期超过了被引用对象的生命周期,那么当你尝试访问被引用对象时,你会遇到不好的事情。这也是any 默认存储副本的部分原因。

【讨论】:

    猜你喜欢
    • 2019-07-30
    • 2015-10-03
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 2016-03-30
    • 1970-01-01
    • 2015-05-16
    相关资源
    最近更新 更多