返回指针而不是vector :: iterator并将vector :: iterator转换为指针

时间:2016-01-17 12:49:10

标签: c++ pointers cuda

我有一个函数,它的返回类型是" vector :: iterator"在下面:

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();
}

问题是,如何将其返回值转换为指针而不是std :: vector迭代器?

我应该将其转换为在CUDA中用于内核,因为我们无法在CUDA中使用向量或其迭代器

这是我的方式:

__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; 
}

用于内核中的工作,例如:

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

但它错了,不起作用,我怎么能这样做?谢谢,

3 个答案:

答案 0 :(得分:2)

您可以执行&(*it),它将提供指向迭代器引用的元素的指针。如果您不知道邪恶用户是否已超载std::addressof(*it),请在std::vector<T>上的通用代码中使用operator&

答案 1 :(得分:1)

如果使用转换意味着不使用向量重写代码,而是使用数组,我建议对代码进行以下调整:

__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. 
}

代码中的主要问题是声明unsigned int *a,b;aunsigned int变量unsigned int创建指针b,但不是两个指针。

第二个问题是第res = &tmp;行(顺便说一下,它的缩进是误导性的。幸运的是gcc 6 will warn you in future )。这导致您返回临时变量的地址。但是一旦从函数返回就会销毁一个临时变量,因此返回的指针将指向一个无处(透视中的UB)。

答案 2 :(得分:1)

原则上你可以使用&*i来获取指向迭代器元素的指针,从而获得基础矢量数据,但这不会帮助你。

你的第一个函数被破坏了,因为它将一个迭代器返回到一个向量,该函数的生命周期在函数返回时结束。

要解决此问题,您可以通过引用获取向量,

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

但索引比迭代更强大,并且与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);

(迭代器用于迭代 - 它们意味着是短暂的和短暂的。 你不应该将它们用作一种通用指针。)

当CUDA代码返回指向arr的指针时,CUDA代码返回一个同样错误的指向自动局部变量的指针:

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