我如何获得指向集合中第一个元素的指针
int main()
{
std::vector<int> v ;
v.insert(v.end() , 1);
v.insert(v.end() , 2);
v.insert(v.end() , 5);
v.insert(v.end() , 4);
std::set<int> s ;
s.insert(s.end() , 754);
s.insert(s.end() , 5);
s.insert(s.end() , 3);
s.insert(s.end() , 4);
std::list<int> l ;
l.insert(l.end() , 45);
l.insert(l.end() , 5);
l.insert(l.end() , 3);
l.insert(l.end() , 4);
int *p = (int*)(&*l.begin()); <<<<<<-------- ( here )
cout << *p++ <<endl;
cout << *p++ <<endl;
cout << *p++ <<endl;
cout << *p <<endl;
它可以与vectors一起使用,但是它给我提供了set和list的垃圾值 任何想法吗?
答案 0 :(得分:2)
在使用指针算术和容器时要非常小心。 std :: vector使用连续的内存,并且指针将按预期工作。其他容器可能不会在连续内存中存储信息,并且增加指针可能无法遍历该容器。
改为使用迭代器。例如:
std::set<int> s;
//add stuff to the set
auto setit = s.begin(); //setit is an iterator for s
cout << *setit++ << endl;
//etc.
迭代器知道如何遍历容器,并且可以使用与指针类似的方法,尽管有区别。值得阅读有关您计划使用的容器的文档-查找可以使用哪种类型的迭代器,以及哪些操作会使迭代器无效。
例如,阅读documentation for std::set。它描述了可以使用的迭代器类型。在每个修饰符的文档中,它还告诉迭代器是否无效。例如,如果您在集合中使用insert
,则迭代器不会无效。
答案 1 :(得分:0)
@rsjaffe是正确的,您应该使用iterator
。
但是,您正在使用对象。
这些对象有一些责任,即以一定的保证金来存储物品。
含糊:
std::vector
的项目进行快速读/写访问std::set
时保留一个(以及相对较快的插入和检索...)std::list
这些类的目标是使这些概念起作用,同时隐藏其内部作用。
从逻辑上讲,您有一个带有漂亮按钮的漂亮遥控器,但是您不知道它们的工作方式,并且制造商不提供任何保证,它将以相同的方式超时工作。您只知道它有效(或者您可以根据需要对其进行测试)。
以同样的方式,Iterators
是封装了横向集合的事物。
在std::set
中没有指向头部的指针,因为元素不是那样保留的。
从这种角度来看,将std::vector::iterator
强制转换为指针的操作是偶然的,而问题是无关紧要。
答案 2 :(得分:0)
因为向量的内存布局是所包含元素类型的连续内存位置,所以创建的指针是普通的C指针。
对于集合和列表,包含的元素是结构的一部分。对于列表,可能是这样的:
struct list {
int value;
struct list *next;
}
或
struct list {
struct list *next;
int value;
}
看起来非常像C,没有模板和方法。因此,当您使用结构体的地址时,您可以读取该值或下一个指针,但是当将指针增加到int时,如果还没有该指针,则会得到一个垃圾值。
在设置和列出的情况下,它甚至不能帮助您拥有正确的指针类型,即。指向结构列表的指针,因为它们在内存中不连续,因此增加它们将无法获得正确的值。