将迭代器转换为指针?

发布于 2024-07-17 03:58:53 字数 743 浏览 2 评论 0 原文

我有一个带有 n 元素的 std::vector 。 现在我需要将一个指向具有最后 n-1 个元素的向量的指针传递给函数。

例如,我的 vector foo 包含 (5,2,6,87,251)。 函数接受 vector*,我想向它传递一个指向 (2,6,87,251) 的指针。

我可以(安全地)获取迭代器++foo.begin(),将其转换为指针并将其传递给函数吗? 或者使用&foo[1]

更新:人们建议我更改函数以采用迭代器而不是指针。 在我的情况下这似乎是不可能的,因为我提到的函数是 unordered_setfind 函数。 因此,在这种情况下,将 n-1 元素从 foo 复制到新向量中,并使用指向该指针的指针调用 find 是唯一的选择? 效率极低! 这就像画家 Shlemiel,特别是因为我必须查询许多子集:最后一个 n-1,然后 n-2 等元素,并查看它们是否在unordered_set

I have a std::vector with n elements. Now I need to pass a pointer to a vector that has the last n-1 elements to a function.

For example, my vector<int> foo contains (5,2,6,87,251). A function takes vector<int>* and I want to pass it a pointer to (2,6,87,251).

Can I just (safely) take the iterator ++foo.begin(), convert it to a pointer and pass that to the function? Or use &foo[1]?

UPDATE: People suggest that I change my function to take an iterator rather than a pointer. That seems not possible in my situation, since the function I mentioned is the find function of unordered_set<std::vector*>. So in that case, is copying the n-1 elements from foo into a new vector and calling find with a pointer to that the only option? Very inefficient! It's like Shlemiel the painter, especially since i have to query many subsets: the last n-1, then n-2, etc. elements and see if they are in the unordered_set.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

黯然#的苍凉 2024-07-24 03:58:54

例如,我的 vector foo 包含 (5,2,6,87,251)。 函数采用 vector*,我想向它传递一个指向 (2,6,87,251) 的指针。

指向向量的指针与指向向量元素的指针完全不同。

为此,您需要创建一个新的 vector,其中仅包含您想要向其中传递指针的元素。 类似于:

 vector<int> tempVector( foo.begin()+1, foo.end());

 // now you can pass &tempVector to your function

但是,如果您的函数采用指向 int 数组的指针,那么您可以传递 &foo[1]

For example, my vector<int> foo contains (5,2,6,87,251). A function takes vector<int>* and I want to pass it a pointer to (2,6,87,251).

A pointer to a vector<int> is not at all the same thing as a pointer to the elements of the vector.

In order to do this you will need to create a new vector<int> with just the elements you want in it to pass a pointer to. Something like:

 vector<int> tempVector( foo.begin()+1, foo.end());

 // now you can pass &tempVector to your function

However, if your function takes a pointer to an array of int, then you can pass &foo[1].

半岛未凉 2024-07-24 03:58:54

你的问题的直接答案是肯定的。 如果 foo 是一个向量,你可以这样做:&foo[1]。

然而,这仅适用于向量,因为标准规定向量通过使用连续内存来实现存储。

但是您仍然可以(并且可能应该)传递迭代器而不是原始指针,因为它更具表现力。 传递迭代器不会复制向量。

The direct answer to your question is yes. If foo is a vector, you can do this: &foo[1].

This only works for vectors however, because the standard says that vectors implement storage by using contigious memory.

But you still can (and probably should) pass iterators instead of raw pointers because it is more expressive. Passing iterators does not make a copy of the vector.

伊面 2024-07-24 03:58:54

使用 vector::front ,应该是最便携的解决方案。 当我与需要 char ptr 的固定 API 接口时,我使用过这个。 例子:

void funcThatTakesCharPtr(char* start, size_t size);

...

void myFunc(vector<char>& myVec)
{
    // Get a pointer to the front element of my vector:
    char* myDataPtr = &(myVec.front());

    // Pass that pointer to my external API:
    funcThatTakesCharPtr(myDataPtr, myVec.size());
}

Use vector::front, it should be the most portable solution. I've used this when I'm interfacing with a fixed API that wants a char ptr. Example:

void funcThatTakesCharPtr(char* start, size_t size);

...

void myFunc(vector<char>& myVec)
{
    // Get a pointer to the front element of my vector:
    char* myDataPtr = &(myVec.front());

    // Pass that pointer to my external API:
    funcThatTakesCharPtr(myDataPtr, myVec.size());
}
玩物 2024-07-24 03:58:54

如果你的函数确实需要 vector; * (指向向量的指针),那么您应该传递 &foo 因为那将是指向向量的指针。 显然,这并不能简单地解决您的问题,但是您不能直接将迭代器转换为向量,因为迭代器地址处的内存不会直接寻址有效的向量。

您可以通过调用向量构造函数来构造一个新的向量:

template <class InputIterator> vector(InputIterator, InputIterator)

这会构造一个新的 向量通过复制两个迭代器之间的元素来向量。 您将大致像这样使用它:

bar(std::vector<int>(foo.begin()+1, foo.end());

If your function really takes vector<int> * (a pointer to vector), then you should pass &foo since that will be a pointer to the vector. Obviously that will not simply solve your problem, but you cannot directly convert an iterator to a vector, since the memory at the address of the iterator will not directly address a valid vector.

You can construct a new vector by calling the vector constructor:

template <class InputIterator> vector(InputIterator, InputIterator)

This constructs a new vector by copying the elements between the two iterators. You would use it roughly like this:

bar(std::vector<int>(foo.begin()+1, foo.end());
友欢 2024-07-24 03:58:54

我还没有测试过这个,但是你可以使用一组迭代器对吗? 每个迭代器对将代表序列向量的开始和结束迭代器。 例如:

typedef std::vector<int> Seq;
typedef std::pair<Seq::const_iterator, Seq::const_iterator> SeqRange;

bool operator< (const SeqRange& lhs, const SeqRange& rhs)
{
    Seq::const_iterator lhsNext = lhs.first;
    Seq::const_iterator rhsNext = rhs.first;

    while (lhsNext != lhs.second && rhsNext != rhs.second)
        if (*lhsNext < *rhsNext)
            return true;
        else if (*lhsNext > *rhsNext)
            return false;

    return false;
}

typedef std::set<SeqRange, std::less<SeqRange> > SeqSet;

Seq sequences;

void test (const SeqSet& seqSet, const SeqRange& seq)
{
    bool find = seqSet.find (seq) != seqSet.end ();
    bool find2 = seqSet.find (SeqRange (seq.first + 1, seq.second)) != seqSet.end ();
}

显然向量必须像以前一样保存在其他地方。 此外,如果修改了序列向量,则必须删除并重新添加其在集合中的条目,因为迭代器可能已更改。

乔恩

I haven't tested this but could you use a set of pairs of iterators instead? Each iterator pair would represent the begin and end iterator of the sequence vector. E.g.:

typedef std::vector<int> Seq;
typedef std::pair<Seq::const_iterator, Seq::const_iterator> SeqRange;

bool operator< (const SeqRange& lhs, const SeqRange& rhs)
{
    Seq::const_iterator lhsNext = lhs.first;
    Seq::const_iterator rhsNext = rhs.first;

    while (lhsNext != lhs.second && rhsNext != rhs.second)
        if (*lhsNext < *rhsNext)
            return true;
        else if (*lhsNext > *rhsNext)
            return false;

    return false;
}

typedef std::set<SeqRange, std::less<SeqRange> > SeqSet;

Seq sequences;

void test (const SeqSet& seqSet, const SeqRange& seq)
{
    bool find = seqSet.find (seq) != seqSet.end ();
    bool find2 = seqSet.find (SeqRange (seq.first + 1, seq.second)) != seqSet.end ();
}

Obviously the vectors have to be held elsewhere as before. Also if a sequence vector is modified then its entry in the set would have to be removed and re-added as the iterators may have changed.

Jon

与君绝 2024-07-24 03:58:54

Vector 是一个模板类,将类的内容转换为指针是不安全的:
您无法继承向量类来添加此新功能。
改变函数参数实际上是一个更好的主意。
Jst 创建另一个 int 向量
向量 temp_foo (foo.begin[X],foo.end());
并将这个向量传递给你的函数

Vector is a template class and it is not safe to convert the contents of a class to a pointer :
You cannot inherit the vector class to add this new functionality.
and changing the function parameter is actually a better idea.
Jst create another vector of int
vector temp_foo (foo.begin[X],foo.end());
and pass this vector to you functions

落日海湾 2024-07-24 03:58:54

将迭代器转换为指针的安全版本(无论其含义如何,这到底意味着什么),并且安全的意思是不必担心必须取消引用迭代器并由于 end() / 其他情况

#include <iostream>
#include <vector>
#include <string.h>

int main()
{
    std::vector<int> vec;

    char itPtr[25];
    long long itPtrDec;
    
    std::vector<int>::iterator it = vec.begin();
    memset(&itPtr, 0, 25);
    sprintf(itPtr, "%llu", it);
    itPtrDec = atoll(itPtr);
    printf("it = 0x%X\n", itPtrDec);
    
    vec.push_back(123);
    it = vec.begin();
    memset(&itPtr, 0, 25);
    sprintf(itPtr, "%llu", it);
    itPtrDec = atoll(itPtr);
    printf("it = 0x%X\n", itPtrDec);
}

会打印类似的内容

它=0x0

它=0x2202E10

这是一种令人难以置信的 hacky 方法,但如果你需要它,它就能完成工作。 您将收到一些编译器警告,如果确实困扰您,可以使用 #pragma 将其删除

A safe version to convert an iterator to a pointer (exactly what that means regardless of the implications) and by safe I mean no worries about having to dereference the iterator and cause possible exceptions / errors due to end() / other situations

#include <iostream>
#include <vector>
#include <string.h>

int main()
{
    std::vector<int> vec;

    char itPtr[25];
    long long itPtrDec;
    
    std::vector<int>::iterator it = vec.begin();
    memset(&itPtr, 0, 25);
    sprintf(itPtr, "%llu", it);
    itPtrDec = atoll(itPtr);
    printf("it = 0x%X\n", itPtrDec);
    
    vec.push_back(123);
    it = vec.begin();
    memset(&itPtr, 0, 25);
    sprintf(itPtr, "%llu", it);
    itPtrDec = atoll(itPtr);
    printf("it = 0x%X\n", itPtrDec);
}

will print something like

it = 0x0

it = 0x2202E10

It's an incredibly hacky way to do it, but if you need it, it does the job. You will receive some compiler warnings which, if really bothering you, can be removed with #pragma

山川志 2024-07-24 03:58:54
std::vector<int> v;
  :
auto it=v.end();
auto ptr=v.data()+std::distance(v.begin(),it);
std::vector<int> v;
  :
auto it=v.end();
auto ptr=v.data()+std::distance(v.begin(),it);
乖乖哒 2024-07-24 03:58:53

在这里,获取对迭代器的相应指针的引用,使用:

示例:

string my_str= "hello world";

string::iterator it(my_str.begin());

char* pointer_inside_buffer=&(*it); //<--

[注意运算符 * 返回一个引用,这样做 & 参考会给你地址]。

here it is, obtaining a reference to the coresponding pointer of an iterator use :

example:

string my_str= "hello world";

string::iterator it(my_str.begin());

char* pointer_inside_buffer=&(*it); //<--

[notice operator * returns a reference so doing & on a reference will give you the address].

怎言笑 2024-07-24 03:58:53

这在我的情况下似乎不可能,因为我提到的函数是 unordered_set 的 find 函数。

您是否使用自定义哈希/谓词函数对象? 如果没有,则必须将 unordered_set*>::find() 指针传递给您要查找的确切向量。 指向具有相同内容的另一个向量的指针将不起作用。 至少可以说,这对于查找来说不是很有用。

使用unordered_set; > 会更好,因为这样您就可以按值执行查找。 我认为这还需要一个自定义哈希函数对象,因为据我所知,hash 没有针对 vector 的专门化。

不管怎样,正如其他人所解释的那样,指向向量中间的指针本身并不是向量。 如果不复制其内容,则无法将迭代器转换为指向向量的指针。

That seems not possible in my situation, since the function I mentioned is the find function of unordered_set<std::vector*>.

Are you using custom hash/predicate function objects? If not, then you must pass unordered_set<std::vector<int>*>::find() the pointer to the exact vector that you want to find. A pointer to another vector with the same contents will not work. This is not very useful for lookups, to say the least.

Using unordered_set<std::vector<int> > would be better, because then you could perform lookups by value. I think that would also require a custom hash function object because hash does not to my knowledge have a specialization for vector<int>.

Either way, a pointer into the middle of a vector is not itself a vector, as others have explained. You cannot convert an iterator into a pointer to vector without copying its contents.

恋你朝朝暮暮 2024-07-24 03:58:53

如果可以的话,更好的选择可能是更改函数以采用元素的迭代器或全新的向量(如果它不修改)。

虽然您可以对数组执行此类操作,因为您知道它们是如何存储的,但对向量执行相同的操作可能是一个坏主意。 &foo[1] 不具有 vector* 类型。

此外,虽然 STL 实现可以在线获得,但尝试依赖抽象的内部结构通常是有风险的。

If you can, a better choice may be to change the function to take either an iterator to an element or a brand new vector (if it does not modify).

While you can do this sort of things with arrays since you know how they are stored, it's probably a bad idea to do the same with vectors. &foo[1] does not have the type vector<int>*.

Also, while the STL implementation is available online, it's usually risky to try and rely on the internal structure of an abstraction.

滴情不沾 2024-07-24 03:58:53

您的函数不应采用 vector*; 它应该适当地采用 vector::iteratorvector::const_iterator 。 然后,只需传入 foo.begin() + 1 即可。

Your function shouldn't take vector<int>*; it should take vector<int>::iterator or vector<int>::const_iterator as appropriate. Then, just pass in foo.begin() + 1.

乄_柒ぐ汐 2024-07-24 03:58:53

向量是一个对其元素具有完全所有权的容器。 一个向量不能包含另一个向量的部分视图,即使是常量视图。 这就是根本原因。

如果您需要,请创建自己的容器,其中包含带有数据的weak_ptr的视图,或者查看范围。 一对迭代器(甚至指针也可以像向量中的迭代器一样工作),或者更好的是,boost::iterator_range 可以非常无缝地工作。

这取决于代码的模板化能力。 如果需要将代码隐藏在 cpp 中,请使用 std::pair。

A vector is a container with full ownership of it's elements. One vector cannot hold a partial view of another, even a const-view. That's the root cause here.

If you need that, make your own container that has views with weak_ptr's to the data, or look at ranges. Pair of iterators (even pointers work well as iterators into a vector) or, even better, boost::iterator_range that work pretty seamlessly.

It depends on the templatability of your code. Use std::pair if you need to hide the code in a cpp.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文