如何确定对象是否已分配成员
How to determine whether an object has heap allocated members?
有没有办法确定对象在堆上至少有一个成员?
我试图能够区分诸如std::string
或std::vector
或std::list
(大多数是容器(之类的对象与所有其他类型(不幸的是,甚至具有单个元素的容器都在我的"感兴趣范围"之内(
我正在尝试做以下操作:
struct foo
{
private:
int * _ptr;
public:
foo() : _ptr(new int) {};
~foo() { delete _ptr; };
};
struct bar
{
private:
int val;
};
template <typename T>
void func(T val)
{
if constexpr (std::is_class_v<T>)
{
std::cout << std::setw(20) << typeid(T).name() << " is a class type." << std::endl;
if (/* determine if foo has any heap allocations */)
{
// Do something #1.
std::cout << std::setw(20) << typeid(T).name() << " does allocate on heap." << std::endl;
}
else
{
// Do something #2.
std::cout << std::setw(20) << typeid(T).name() << " does NOT allocate on heap." << std::endl;
}
}
else
{
// Do something #3.
std::cout << std::setw(20) << typeid(T).name() << " is NOT a class type." << std::endl;
}
}
int main()
{
func(foo()); // foo does allocate on heap
cout << endl;
func(bar()); // bar does NOT allocate on heap
cout << endl;
};
类foo
和bar
仅仅是示例,并且功能func()
必须执行与cout
ING的功能稍有不同。
这是XY问题...我正在尝试编写一个将 请注意,用户定义的密钥类型是否将任何数据存储在数组上 (就像std :: string`一样(。我相当能够创建一个通用 哈希功能采用任何类型,但是如果该类型具有数组(a 指针(到其中一些存储的数据,问题变得非常棘手 (指向动态阵列在运行时更改,同一键在 不同的时间将产生不同的哈希值(
请注意,某些结构/班级类型具有内部非初始化的填充,这可能会使您的哈希功能不正确地起作用。
否则,std::is_trivially_copyable
将是一个很好的开始。
正如其他人在评论中指出的那样,没有办法区分指针指向动态分配的指针。另一方面,C 标准<type_traits>
提供了类型特征,例如
- std :: is_pointer 要检查类型是指针
- std :: is_Array 检查Wether Array类型
- std :: is_bounded_array 检查类型是已知绑定的数组。
等等。看看链接,是否适合您的实际问题。
话虽如此,为什么不能使用会员函数来解决信息?
告诉信息?例如:
struct foo
{
public:
bool isHeapAllocated() const noexcept { return true; }
};
struct bar
{
public:
bool isHeapAllocated() const noexcept { return false; }
};
然后简单地调用函数:
template <typename T> void func(T val)
{
if constexpr (std::is_class_v<T>)
{
if (val.isHeapAllocated()) {
// Do something #1.
}
else
{
// Do something #2.
}
}
else
{
// Do something #3.
}
}
我很确定其他答案是正确的,因为他们说您不应该弄乱试图确定一个对象是否存在在堆或堆栈上,但我必须不同意,但这是"不可能"确定。
以下示例使用Windows(每个OS的过程都会有所不同!(:
#include <Windows.h>
bool isAddressOnHeap(void* address) {
bool returnval = 0;
PROCESS_HEAP_ENTRY entry;
HANDLE procHeap = GetProcessHeap();
if (procHeap == NULL) {
std::cerr << "Failed to retrieve Heap.n";
return -1;
}
if (HeapLock(procHeap) == FALSE) {
std::cerr << "Failed to lock heap.n";
return -1;
}
entry.lpData = NULL;
if (HeapWalk(procHeap, &entry) != 0) {
if (entry.wFlags & PROCESS_HEAP_REGION) {
std::cout << "Function succeeded. The heap begins at " << (void*)entry.Region.lpFirstBlock << " and ends at " << (void*)entry.Region.lpLastBlock << "n";
if (address >= (void*)entry.Region.lpFirstBlock && address <= (void*)entry.Region.lpLastBlock)
returnval = 1;
}
}
if (HeapUnlock(procHeap) == FALSE) {
std::cerr << "Failed to unlock heap.n";
return -1;
}
return returnval;
}
此功能将确定给定地址是否在堆上。这里的测试程序:
int main()
{
int i = 1;
std::cout << "Address of i on Stack: " << (void*)&i << "n";
int* j = new int;
*j = 1;
std::cout << "Address of j on Heap: " << (void*)j << "n";
int* k = (int*)malloc(sizeof(int));
*k = 1;
std::cout << "Address of k on Heap: " << (void*)k << "n";
std::cout << "is i on Heap?: " << isAddressOnHeap(&i) << "n";
std::cout << "is j on Heap?: " << isAddressOnHeap(j) << "n";
std::cout << "is k on Heap?: " << isAddressOnHeap(k) << "n";
delete j;
free(k);
return 0;
}
该程序在我的计算机上返回以下内容:
Address of i on Stack: 0000001062AFFE80
Address of j on Heap: 0000018B11C530B0
Address of k on Heap: 0000018B11C53070
Function succeeded. The heap begins at 0000018B11C40740 and ends at 0000018B11D3F000
is i on Heap?: 0
Function succeeded. The heap begins at 0000018B11C40740 and ends at 0000018B11D3F000
is j on Heap?: 1
Function succeeded. The heap begins at 0000018B11C40740 and ends at 0000018B11D3F000
is k on Heap?: 1
您可以在Microsoft的网站上阅读有关此代码如何工作的更多信息。
在Linux机器上似乎也有类似的方法。
,但作为警告的最后一句话:这个答案只是概念证明!
我试图区分"以成员为成员的数组类型"answers"无数组作为成员的类型"。
您需要查看该代码,因此您需要将功能传递到源代码的路径,您需要对其进行解析。
唯一确定的方法是添加所需的机器来处理每种类型,并且作为必要的单个对象。
以下是任何理智类型的好开始(尊重零/三/五的规则(:
template <class T>
constexpr auto owns_no_dynamic_memory(T const& x) noexcept {
if constexpr (std::is_trivially_copyable_v<T>
|| std::is_trivially_move_constructible_v<T>
|| std::is_trivially_copy_assignable_v<T>
|| std::is_trivially_move_assignable_v<T>
|| std::is_trivially_destructible_v<T>)
return std::true_type();
else
return false;
}
根据需要添加过载。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- C++类成员:堆栈与堆分配
- 为什么在分配给成员变量之前获取unique_ptr的返回是一个问题?
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 在成员初始值设定项列表中分配unique_ptr
- 对象分配-成员函数的使用无效错误
- 如何确定对象是否已分配成员
- 我可以分配成员访问操作员的返回值吗?
- lambda表达式分配成员函数指针
- 如何在C++中从命令行参数分配成员变量
- 为什么分配成员会引发 NullReferenceException
- 错误:在只读对象中分配成员
- 在只读对象中分配成员 '
- 分配成员变量时出现分段错误
- 具有动态分配成员的结构体的向量
- 按值分配成员对象:我的假设是否正确
- 创建std::shared_ptr来分配成员变量时内存泄漏
- 处理包含动态分配成员的对象向量