简体   繁体   中英

return pointer rather than vector::iterator and convert vector::iterator to pointer

i have a function that its return type is "vector::iterator" in below:

vector<unsigned int>::iterator foo(unsigned int arg, vector<unsigned int> arr, vector<unsigned int> M)
{    if (arg == 0)
        return arr.begin();
    else if (arg == 2)
        return arr.begin() + arr[arg - 1];
    else
        return arr.begin();
}

the question is this, how to convert its return value to a pointer rather than of std::vector iterator?

i should be convert it for use to kernel in CUDA because we couldn't use vector or its iterator in CUDA

This is my way:

__host__ __device__ unsigned int* foo(unsigned int arg, unsigned int* arr, unsigned int* M)
{  
    unsigned int* res, tmp;
    if (arg == 0)
        tmp = arr[0];
    else if (arg == 2)
        tmp = arr[0] + arr[arg - 1];
    else
        tmp = arr[0];
        res = &tmp;
    return res; 
}

for work in kernel, for example:

__global__ kernel void kernel . . .
.
.
unsigned int* d_h = foo( , ,)
.
.

but it's wrong and doesn't work, how to could i do it? Thanks,

You can do &(*it) which will provide a pointer to the element that the iterator refers to. Use std::addressof(*it) in generic code over std::vector<T> if you don't know if operator& has been overloaded by evil users.

If with converting you mean rewriting the code without using vectors, but using arrays instead, I'd propose the following adjustments to your code:

__host__ __device__ unsigned int* foo(unsigned int arg, unsigned int* arr, unsigned int* M)
{  
    unsigned int *res, *tmp;  // attention * is per item !! 
    if (arg == 0)
        tmp = arr;  // return a pointer to the begining
    else if (arg == 2)
        tmp = arr + arr[arg - 1];  // you need to make pointer arithmetic like in the original code iterator arithmetics
    else
        tmp = arr;  // keep it simple 
    return tmp;    // note that you don't need res. 
}

The main issue in your code was that declaration unsigned int *a,b; creates a pointer a to an unsigned int and an unsigned int variable b , but not two pointers.

The second issue was the line res = &tmp; ( by the way, its indenting is misleading. Fortunately gcc 6 will warn you in future ). This caused you to return the address of a temporary variable. But a temporary variable is destroyed as soon as you return from the function, so your returned pointer will point to a nowhere place (UB in perspective).

You can in principle use &*i to get a pointer to the iterator's element, and hence the underlying vector data, but that won't help you here.

Your first function is broken, as it returns an iterator into a vector whose lifetime ends when the function returns.

To fix that, you could take the vector by reference,

vector<unsigned int>::iterator foo(unsigned int arg, vector<unsigned int>& arr)
{
    return arg == 2 ? arr.begin() + arr[1] : arr.begin();
}

but indexing is more robust than iterating and behaves well with const-ness:

int foo(unsigned int arg, const vector<unsigned int>& arr)
{
    return arg == 2 ? arr[1] : 0;
}

vector<unsigned int>::iterator it = myvector.begin() + foo(arg, myvector);
vector<unsigned int>::const_iterator cit = myvector.cbegin() + foo(arg, myvector);

(Iterators are for iterating – they're meant to be transient and short-lived.
You shouldn't use them as a kind of generalised pointer.)

The CUDA code returns an equally wrong pointer to an automatic local variable when it should return a pointer into arr :

__host__ __device__ unsigned int* foo(unsigned int arg, unsigned int* arr, unsigned int* M)
{
    return arg == 2 ? arr + arr[1] : arr;  
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM