在C++中对T*类型执行std::move的意外行为

Unexpected behaviour of std::move on T* type in C++

本文关键字:move 意外 std 执行 中对 C++ 类型      更新时间:2023-10-16

我在下面的代码片段中声明了一个名为pval的变量,该变量试图在T*上派生T&&[其中Tint]。根据类型信息[使用abi解码],导出的类型是int*

但当我将int*类型与decltype(pval)进行比较时,它返回零而不是1,这意味着它将pval视为不同于int*的类型。那么哪一个是错误的pvaltypeid报告的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);
}

decltypetypeid的行为不同。

pval的确切类型是int* &&,即对int*的右值引用。(这就是std::is_same在与int*的类型进行比较时返回false的原因。(根据decltype的行为,

如果表达式的值类别是xvalue,则decltype产生T&amp;;

std::move(ptr)返回的是一个x值。

以下表达式是xvalue表达式:

  • 函数调用或重载运算符表达式,其返回类型为对对象的右值引用,如std::move(x)

那么给定decltype(std::move(ptr)) pvalpval的类型将是int* &&

另一方面,typeid的行为不同。

指代表类型typestd::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(。