std::move 在 C++ 中 T* 类型的意外行为
Unexpected behaviour of std::move on T* type in C++
我在下面的代码片段中声明了一个名为 pval
的变量,它试图在 T*
上导出 T&&
[ 其中 T
为 int
].根据类型信息 [使用 abi 解码],派生的类型是 int*
。
但是当我将 int*
类型与 decltype(pval)
进行比较时,它 returns 为零而不是 1,这意味着它将 pval
视为不同于 int*
的不同类型].那么 typeid
或 is_same
报告的 pval
是 int*
是错误的,这表明比较是错误的。
#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);
}
__cxa_demangle()
函数不会为您提供有关 const 和引用限定符的可靠(或任何?)信息。试试这个而不是你的 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;
}
... 这是基于 Howard Hinnant 的代码 here。明显的警告:这仅适用于某些编译器(不适用于 MSVC)。
decltype
和 typeid
的行为不同。
pval
的确切类型是 int* &&
,即 int*
的右值引用。 (这就是为什么 std::is_same
returns false
与 int*
的类型进行比较时的原因。)根据 decltype
,
的行为
if the value category of expression is xvalue, then decltype yields T&&;
而 std::move(ptr)
returns 是 xvalue。
The following expressions are xvalue expressions:
- a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as
std::move(x)
;
然后给定 decltype(std::move(ptr)) pval
,pval
的类型将是 int* &&
。
另一方面,typeid
的行为不同。
Refers to a std::type_info
object representing the type type
. If type
is a reference type, the result refers to a std::type_info
object representing the referenced type.
这意味着 typeid(pval)
返回的 std::type_info
对象将引用引用的类型,即 int*
,而不是 int* &&
。
顺便说一句:什么 std::type_info::name
returns 是实现定义的。
我在下面的代码片段中声明了一个名为 pval
的变量,它试图在 T*
上导出 T&&
[ 其中 T
为 int
].根据类型信息 [使用 abi 解码],派生的类型是 int*
。
但是当我将 int*
类型与 decltype(pval)
进行比较时,它 returns 为零而不是 1,这意味着它将 pval
视为不同于 int*
的不同类型].那么 typeid
或 is_same
报告的 pval
是 int*
是错误的,这表明比较是错误的。
#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);
}
__cxa_demangle()
函数不会为您提供有关 const 和引用限定符的可靠(或任何?)信息。试试这个而不是你的 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;
}
... 这是基于 Howard Hinnant 的代码 here。明显的警告:这仅适用于某些编译器(不适用于 MSVC)。
decltype
和 typeid
的行为不同。
pval
的确切类型是 int* &&
,即 int*
的右值引用。 (这就是为什么 std::is_same
returns false
与 int*
的类型进行比较时的原因。)根据 decltype
,
if the value category of expression is xvalue, then decltype yields T&&;
而 std::move(ptr)
returns 是 xvalue。
The following expressions are xvalue expressions:
- a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as
std::move(x)
;
然后给定 decltype(std::move(ptr)) pval
,pval
的类型将是 int* &&
。
另一方面,typeid
的行为不同。
Refers to a
std::type_info
object representing the typetype
. Iftype
is a reference type, the result refers to astd::type_info
object representing the referenced type.
这意味着 typeid(pval)
返回的 std::type_info
对象将引用引用的类型,即 int*
,而不是 int* &&
。
顺便说一句:什么 std::type_info::name
returns 是实现定义的。