[英]How can I determine whether a void * pointer points to a objective-c object or a c++ object at runtime
[英]How can I print the variable that a void pointer points to
我希望函數根據不同的參數值返回不同的類型,但是如何在main()
打印void指針指向的變量?
#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int param = 5;
return ¶m;
}
else if (a == 2)
{
double param = 5.5;
return ¶m;
}
else if (a == 3)
{
string param = "hello";
return ¶m;
}
else
{
return nullptr;
}
}
int main()
{
void *ptr = func(3);//
cout << ptr;// print the address not the value
getchar();
return 0;
}
param
是一個自動變量。 您不能將其退回並在其范圍之外使用它。
param
僅存在於func
,如果返回,結果為Undefined Behavior。
要修復它,您可以:
param
。 執行此操作后,您可以安全地返回param
地址,但您必須記住在不需要它時將其釋放。 這是對代碼的更正
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int *param = new int(5);
return param;
}
else if (a == 2)
{
double *param = new double(5.5);
return param;
}
else if (a == 3)
{
char *param = new char[50];
strcpy(param, "test");
return param;
}
return nullptr;
}
int main()
{
int *ptr = (int*)func(1);
cout << *ptr << std::endl; // print the int value
delete ptr;
double *ptr2 = (double*)func(2);
cout << *ptr2 << std::endl; // print the double value
delete ptr2;
char *ptr3 = (char*)func(3);
cout << ptr3 << std::endl; // print the string
delete[] ptr3;
getchar();
return 0;
}
如果你可以使用C ++ 17,你可以通過使用std::variant
而不是void *
來輕松解決它:
#include<iostream>
#include<string>
#include<variant>
std::variant<int, double, std::string, void *> func(int a) {
if (a == 1) {
int param = 5;
return param;
} else if (a == 2) {
double param = 5.5;
return param;
} else if (a == 3) {
std::string param = "hello";
return param;
} else {
return nullptr;
}
}
int main() {
std::visit([](auto v) {
std::cout << v << std::endl;
}, func(3));
}
在C ++ 11/14中,您可以使用帶標記的聯合執行相同的操作。 基本的想法是,您返回的內容包含足夠的信息,以便調用者可以從中獲取原始類型。
存在替代方案。
例如,您可以擦除類型並返回包含原始(已擦除)變量和指向函數的指針的對,該函數填充了函數模板的實例。 后者將能夠從void *
重建原始變量,因為它知道它的類型。
好吧,幾乎是一個很棒的機器,你可以避免使用帶標記的union或std::variant
(在一天結束時或多或少是類型安全版本的標記聯合)。
你要返回的是局部變量的地址。 當函數返回時,該變量超出范圍,這意味着它正在使用的內存可以重用。 嘗試取消引用該指針(即訪問它指向的內存)會調用未定義的行為 。
即使您返回一個有效的指針,您的函數返回void *
的事實意味着有關該指針指向的內容的任何類型信息都將丟失。 您可以從該地址開始打印一個或多個字節,但它不會告訴您原始類型是什么。
即使該指針有效,您也無法獲得足夠的信息來強制轉換為某些東西,然后將其打印出來。 沒有關於其大小的信息,沒有其內部布局的信息。 所以,你根本無法打印void *指向的內容,除非你手邊有一些手工准備的信息,並強制static_cast為已知類型。 例如:
double x = 1.2;
int y = 5;
int f(void** output) {
static int x;
if ( x++ ) {
*output = &x;
return 1;
}
*output = &y;
return 2;
}
...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.