C++ 创建一个;参考向量;仅使用标准库
我想创建一个对象,将该对象放入C++ 创建一个;参考向量;仅使用标准库,c++,pointers,vector,reference,standard-library,C++,Pointers,Vector,Reference,Standard Library,我想创建一个对象,将该对象放入向量,并且仍然能够通过仅访问向量来修改相同的对象。但是,我知道当一个对象是push_back()到向量时,该对象实际上被复制到向量。因此,访问向量中的对象只会访问相似但不同的对象 我有C语言的初学者知识,所以我知道我可以创建指向对象的指针,并生成指针向量。e、 g.向量。但是,似乎是在C++中,并且。然而 我只希望使用标准库,因此boost是我的禁区 我听说过智能指针。但是,似乎存在多种类型的智能指针。这样做会不会太过分了?如果智能指针确实是答案,那么我如何确定使用
向量
,并且仍然能够通过仅访问向量
来修改相同的对象。但是,我知道当一个对象是push_back()
到向量
时,该对象实际上被复制到向量
。因此,访问向量中的对象只会访问相似但不同的对象
我有C语言的初学者知识,所以我知道我可以创建指向对象的指针,并生成指针向量。e、 g.向量
。但是,似乎是在C++中,并且。然而
我只希望使用标准库,因此boost
是我的禁区
我听说过智能指针。但是,似乎存在多种类型的智能指针。这样做会不会太过分了?如果智能指针确实是答案,那么我如何确定使用哪一个呢
所以我的问题是:创建对象的引用/指针向量的标准做法是什么?
换句话说,我希望下面的(伪)代码能够工作
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Object
{
public:
int field;
};
vector<Object> addToVector(Object &o)
{
vector<Object> v;
v.push_back(o);
v[0].field = 3; // I want this to set o.field to 3.
return v;
}
int main()
{
Object one;
one.field = 1;
cout << one.field << endl; // 1 as expected
Object &refone = one;
refone.field = 2;
cout << one.field << endl; // 2 as expected
vector<Object> v = addToVector(one);
cout << v[0].field << endl; // 3 as expected
cout << one.field << endl; // I want to get 3 here as well, as opposed to 2.
return 0;
}
#包括
#包括
#包括
使用名称空间std;
类对象
{
公众:
int字段;
};
向量addToVector(对象和对象)
{
向量v;
v、 推回(o);
v[0].field=3;//我希望将o.field设置为3。
返回v;
}
int main()
{
对象一;
1.字段=1;
库特
我想创建一个对象,将该对象放入一个向量,并且仍然能够通过只访问向量来修改同一个对象。但是,我知道当一个对象是push_back()时
对于向量,对象实际上被复制到向量中。因此,访问向量中的对象只会访问相似但不同的对象
我几乎可以肯定这不是你想要或“应该”想要的。请原谅我直接打开我的答案,但除非你有很好的理由这样做,否则你可能不想这样做
对于这一点-带引用的向量-要工作,您必须保证在保存引用对象时,引用对象不会被移动或破坏。如果向量中有引用对象,请确保该向量未调整大小。如果堆栈中有引用对象,如示例中所示,则不要让引用向量或其副本离开固定框架。如果您想将它们存储在某个容器中,请使用std::list
(它是迭代器,基本上是指针,在插入或删除元素时不会失效)
<>你已经注意到你不能有一个“真实”的引用向量。因此,引用是不可指派的。考虑下面的代码:
int a = 42;
int b = 21;
int & x = a; // initialisation only way to bind to something
int & y = b;
x = y;
b = 0;
在这之后,您从x
获得的值将是21,因为赋值没有更改引用(绑定到b
),而是更改了引用对象a
。但是a改变了这一点
您现在可以开始编写一个围绕指针的包装器,如
template<typename T>
struct my_ref {
T * target;
// don't let one construct a my_ref without valid object to reference to
my_ref(T & t) : target(&t) {}
// implicit conversion into an real reference
operator T &(void) {
return *target;
}
// default assignment works as expected with pointers
my_ref & operator=(my_ref const &) = default;
// a moved from reference doesn't make sense, it would be invalid
my_ref & operator=(my_ref &&) = delete;
my_ref(my_ref &&) = delete;
// ...
};
()
现在有人可能会争论为什么在指针周围使用包装器,比如std::reference_wrapper
,而人们也可以直接使用指针。在我看来,指针可以是nullptr
,它改变了代码的语义:当你有一个原始指针时,它可能是无效的。当然,你可以假设它不是,或者把它放在什么地方在评论中没有提到,但最终你会依赖一些代码无法保证的东西(这种行为通常会导致bug)
如果向量的一个元素可能“引用”一个对象或无效,那么原始指针仍然不是第一选择(对我来说):当使用向量中有效的元素时,它引用的对象实际上是从代码的多个位置引用的;它是共享的然后,对对象的引用应该是a和向量s的元素。然后,您可以(线程安全)在需要时获取有效的“引用”(共享指针),并在完成时删除它:
auto object = make_shared<int>(42);
vector<weak_ptr<int>> v;
v.push_back (object);
// ... somewhere later, potentially on a different thread
if (auto ref = v[0].lock()) {
// noone "steals" the object now while it's used here
}
// let them do what they want with the object, we're done with it ...
auto object=make_shared(42);
向量v;
v、 推回(物体);
//…稍后的某个地方,可能在另一个线程上
if(auto ref=v[0].lock()){
//在这里使用时,现在没有人“窃取”该对象
}
//让他们对这个物体做他们想做的事,我们已经完成了。。。
最后,请恕我直言,我的回答大多基于我的观点(和经验),可能不算“标准做法”.指针向量没有问题,只要该向量不需要担心它们指向的对象的生命周期。请使用智能指针向量。我很确定这个问题是重复的。如果是重复的话,很抱歉。我发现的唯一一个类似于我的问题建议使用boost,我希望避免。我如果这确实是重复的,请让我知道。只需使用指针向量。这里不需要智能指针。按一下,您可以使用std::reference\u wrapper
。解决原始问题的方法是使用vector::emplace\u back
,这是在C++11中引入的。它从argum在向量中创建一个对象ent列表;例如,v.emplace\u back()
(参数列表为空)使用默认构造函数(或非类类型的值初始化)在向量中创建新对象。该对象不会被复制或移动到向量中,而是在适当的位置创建的。std::vector
因为C++11不需要CopySassignable。我认为不能有引用向量的根本原因是不能有指向引用的指针。因此,不可能放置新的引用,迭代器需要研发工作区。
auto object = make_shared<int>(42);
vector<weak_ptr<int>> v;
v.push_back (object);
// ... somewhere later, potentially on a different thread
if (auto ref = v[0].lock()) {
// noone "steals" the object now while it's used here
}
// let them do what they want with the object, we're done with it ...