为何void*右值引用可绑定左值,int*右值引用却报错?
为什么
int*&&绑定左值报错,void*&&却可以? 这是个非常典型的C++类型系统和引用绑定规则的交互问题,咱们一步步拆解:
1. 第一个报错的原因(int*&& irr = iptr;)
你已经理解得很对:iptr是int*类型的左值,而普通的右值引用(T&&,这里T是int*)只能绑定到右值(比如临时对象、字面量、std::move后的左值)。直接把左值绑定到非万能的右值引用上,编译器自然会抛出你看到的错误:
error: rvalue reference to type 'int *' cannot bind to lvalue of type 'int *'
2. void*&& irr = iptr;能编译的核心原因
这里触发了C++的隐式类型转换+临时对象生命周期延长规则:
- 首先,
iptr是int*类型的左值,C++允许int*隐式转换为void*(这是标准规定的指针向上转换,用于泛型内存操作); - 这个转换的结果是一个**
void*类型的临时右值**(因为转换操作生成的是临时对象,不属于任何命名变量,是右值); - 而右值引用
void*&&恰好可以绑定到这个临时右值上,同时根据C++标准,当右值引用绑定到临时对象时,临时对象的生命周期会被延长至引用的生命周期结束——也就是说这个临时的void*指针会和irr一起存活到当前作用域结束。
3. 运行时行为是否安全?
完全安全,没有未定义行为:
irr绑定的临时void*指针的值和iptr完全一致(就是原指针指向的内存地址);- 你可以正常使用
irr,比如把它转换回int*去访问原变量,只要转换的类型正确,就不会有任何问题; - 唯一需要注意的是:
void*本身不携带类型信息,后续转换时要确保类型匹配,避免类型错误导致的未定义行为,但这和右值引用绑定本身无关。
举个类似的非指针例子你就能更清楚:double&& d = 42;,这里42是int左值,编译器先把它转换为double临时右值,再绑定到double&&上,和你的指针场景本质完全相同。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

