在C++中对T*类型执行std::move的意外行为
Unexpected behaviour of std::move on T* type in C++
我在下面的代码片段中声明了一个名为pval
的变量,该变量试图在T*
上派生T&&
[其中T
是int
]。根据类型信息[使用abi解码],导出的类型是int*
。
但当我将int*
类型与decltype(pval)
进行比较时,它返回零而不是1,这意味着它将pval
视为不同于int*
的类型。那么哪一个是错误的pval
是typeid
报告的int*
还是指示比较为假的is_same
。
#include<iostream>
#include<string>
#include<typeinfo>
#include<cxxabi.h>
#include<type_traits>
using namespace std;
std::string classname(const std::type_info& info)
{
int status;
char* rslt=abi::__cxa_demangle(info.name(),0,0,&status);
std::string result(rslt);
free(rslt);
return result;
}
int main(int argc, char* argv[])
{
int* ptr = new int(10);
decltype(std::move(ptr)) pval = std::move(ptr);
cout << classname(typeid(pval)) << endl; // as per typeid information the type of pval is int*.
bool isSame = is_same<decltype(pval), int*>::value; // What then is the pval not same as int* as per is_same ?
cout << "isSame status = " << isSame << endl;
cout << is_same<int*, int*>::value << endl;
return(0);
}
decltype
和typeid
的行为不同。
pval
的确切类型是int* &&
,即对int*
的右值引用。(这就是std::is_same
在与int*
的类型进行比较时返回false
的原因。(根据decltype
的行为,
如果表达式的值类别是xvalue,则decltype产生T&;;
std::move(ptr)
返回的是一个x值。
以下表达式是xvalue表达式:
- 函数调用或重载运算符表达式,其返回类型为对对象的右值引用,如
std::move(x)
那么给定decltype(std::move(ptr)) pval
,pval
的类型将是int* &&
。
另一方面,typeid
的行为不同。
指代表类型
type
的std::type_info
对象。如果type
是引用类型,则结果引用表示引用类型的std::type_info
对象。
这意味着typeid(pval)
返回的std::type_info
对象将引用引用的类型,即int*
,而不是int* &&
。
BTW:std::type_info::name
返回的是定义的实现
__cxa_demangle()
函数不能为您提供有关常量和引用限定符的可靠(或任何?(信息。试试这个,而不是你的classname()
功能:
template <typename T, bool WithCVCorrections = true>
std::string type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own(
abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr),
std::free
);
std::string r = (own != nullptr) ? own.get() : typeid(TR).name();
if (WithCVCorrections) {
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
}
return r;
}
这是基于霍华德·欣南特的代码。明显的警告:这只适用于某些编译器(而不是MSVC(。
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- Usages of std::move
- 在C++中对T*类型执行std::move的意外行为
- 关于std::move的使用,是否有编译警告
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 处理除以零会导致<csignal>意外行为
- 通过实例理解std::move及其目的
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 使用vscode调试时,GDB意外退出
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 基于范围的 std::move 调用意外复制构造函数
- 与move构造函数配对时,会发生意外的析构函数调用
- 组合 std::forward、std::move 和 voltile 时出现意外的返回类型
- std::move 意外调用析构函数