【发布时间】:2020-11-01 19:15:09
【问题描述】:
我可以从T* 中获取T*&。现在我需要以类型擦除的方式存储我的T*,更具体地说是void*。我可以从void* 中获取T*& 吗? (当然知道我的void* 确实指向Ts)
例子:
#include <iostream>
#include <cstdlib>
#include <numeric>
int main() {
int n = 10;
void* mdbuf = malloc(n*sizeof(double));
double* mdarr = (double*)mdbuf;
std::iota(mdarr,mdarr+n,0.); // initialize the memory with doubles
// solution 1: works but not what I want since I want to refer to the type-erased mdbuf variable
double*& mdarr_ref = mdarr; // ok, now mdarr_ref refers to variable mdarr
// solution 2: does not compile
double*& mdbuf_ref = (double*)mdbuf; // error: cannot bind non-const lvalue reference of type 'double*&' to an rvalue of type 'double*'
// solution 3: compiles and work but I want to be sure this is not out of pure luck: is it undefined behavior?
double*& mdbuf_ref = (double*&)mdbuf; // we would like mdbuf_ref to refer to variable mdbuf. It compiles...
std::iota(mdbuf_ref,mdbuf_ref+n,100.);
for (int i=0; i<n; ++i) {
std::cout << mdbuf_ref[i] << ", "; // ...does what we want in this case... is it valid however?
}
}
编辑:也许一种看待它的方式如下:
double d;
void* v_ptr = &d;
double* d_ptr = (double*)v_ptr; // (1) valid
double& d_ref = d; // (2) valid
double& d_ref2 = (double&)d; // (3) valid? Should be the same as (2) ?
double*& d_ref3 = (double*&)v_ptr; // (4)
问题是:(4) 有效吗?如果(1)和(3)成立,它只是链接两者,所以我希望它是有效的,但我想要一些证据
【问题讨论】:
-
你有一个引用有意义的用例吗?
-
不,这是不合法的。在字可寻址系统上,
sizeof(void*) != sizeof(double*)。void*由地址 + 字节索引组成,而不仅仅是地址。 -
@RaymondChen 我很惊讶。你有资源吗 ?不合法是什么意思?实现定义或未定义的行为?在我关心的所有系统上
sizeof(void*) == sizeof(double*) -
在您的示例中,您的任何地方都没有
double类型的对象(我猜是您的T)。仅仅因为你为它保留空间并不意味着你有一个对象。因此,尽管如果您创建这样的对象(如在解决方案 1 中),您可以获取对double*的引用,但您将永远无法使用该指针执行任何操作。 (语言律师标签) -
@Bérenger 为什么你仍然坚持 mallocing 这个东西?如果你使用
new(或者甚至使用std::array或std::vector)正确地做到这一点,你就已经有了一个有效的对象和一个具有正确类型的指向它的指针。
标签: c++ language-lawyer