将deque转换为void指针是否安全

Is casting a deque to and from void pointer safe?

本文关键字:指针 是否 安全 void deque 转换      更新时间:2023-10-16

文档中说

与vector不同,deque不能保证将其所有元素存储在连续的存储位置

这是否意味着如果我将deque转换为void *,然后返回到原始deque,我可能会在里面得到一些随机数据?

不,这意味着你不能接受deque的第一个元素的地址,将其强制转换为指针,然后在假设其余元素是连续顺序的情况下执行指针算术:

deque<int> d;
//...
int* x = &(d[0]);
int secondElement = x[1]; // illegal 
vector<int> v;
//...
int* x = &(v[0]);
int secondElement = x[1]; // legal

您可以将deque的地址强制转换为void*,然后再将其强制转换回来。

No。不是这个意思。首先,不能deque强制转换为void*。这两个将有不同的大小,这将打破对象。

它的实际意思是你可以这样做:

vector<int> myVec = ...;
int* theBuffer = &myVec[0]; // In C++ 11, you can also do myVec.data() instead

theBuffer将是一个连续的内存段,所以你可以把它传递给一个C函数期望一个指针,例如(见下文),使用指针算术访问它,等等。deque不能这样做,因为它的内部表示不提供这样的保证。注意,这与存储在vectordeque中的数据有关,而与对象本身无关。如果您想将指向deque的指针存储在void*中,您可以自由地这样做。

// Example: A C function
extern "C" void a_c_function(int* data, const size_t num_elements);
// Invoking it on a vector's elements
a_c_function(&myVec[0], myVec.size());

不能将结构体强制转换为指针。reinterpret_cast可能会用一些未知的语义编译,但它只是要求打破:deque将至少有两个指针大,所以它不能装进一个指针。

您可以将deque<…> *转换为void *并返回。这与deque的内容无关,但它只是取容器对象本身的地址。

std::deque< int > dq;
void * x = reinterpret_cast< void * >( dq ); // Nonsense.
void * y = static_cast< void * >( & dq ); // Type-erased ptr to object, OK.
std::deque< int > & dqr = * static_cast< std::deque< int > * >( y ); // restore type, OK.

dequevector之间的相关区别在于它们的迭代器:可以像使用vector::iterator一样使用指向vector元素的指针,因为vector使用连续存储。然而,在deque中导航的唯一方法是deque::iterator

int * vf = & vec.front(); // Ptr to first element
int * velem = vf + 10; // OK if vec has 10 elements.
int * df = & dq.front(); // Ptr to first element
int * delem = df + 10; // Error, although it might work sometimes.