[英]How can I print the variable that a void pointer points to
I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to in main()
? 我希望函数根据不同的参数值返回不同的类型,但是如何在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
is an automatic variable. param
是一个自动变量。 You cannot return it and use it outside its scope. 您不能将其退回并在其范围之外使用它。
param
exists only within func
, if you return it, the result is Undefined Behaviour. param
仅存在于func
,如果返回,结果为Undefined Behavior。
To fix it you can either: 要修复它,您可以:
param
on the heap dynamically. 动态地在堆上分配param
。 After you do that, you can safely return param
address but you have to remember to free it when you don't need it. 执行此操作后,您可以安全地返回param
地址,但您必须记住在不需要它时将其释放。 Here is correction of your code 这是对代码的更正
#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;
}
If you can use C++17, you can easily solve it by using a std::variant
instead of a void *
: 如果你可以使用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));
}
See it up and running on wandbox . 在wandbox上查看并运行它 。
In C++11/14 you can do the same with a tagged union . 在C ++ 11/14中,您可以使用带标记的联合执行相同的操作。 The basic idea is that what you return contains enough information so that the caller can get out of it the original type. 基本的想法是,您返回的内容包含足够的信息,以便调用者可以从中获取原始类型。
Alternatives exist. 存在替代方案。
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. 例如,您可以擦除类型并返回包含原始(已擦除)变量和指向函数的指针的对,该函数填充了函数模板的实例。 The latter will be able to reconstruct the original variable from a void *
for it knows its type. 后者将能够从void *
重建原始变量,因为它知道它的类型。
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant
(more or less a type-safe version of a tagged union at the end of the day). 好吧,几乎是一个很棒的机器,你可以避免使用带标记的union或std::variant
(在一天结束时或多或少是类型安全版本的标记联合)。
What you're returning is the address of a local variable. 你要返回的是局部变量的地址。 That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. 当函数返回时,该变量超出范围,这意味着它正在使用的内存可以重用。 Attempting to dereference that pointer (ie access the memory it points to) invokes undefined behavior . 尝试取消引用该指针(即访问它指向的内存)会调用未定义的行为 。
Even if you were returning a valid pointer, the fact that your function returns a void *
means that any type information regarding what that pointer was pointing to is lost. 即使您返回一个有效的指针,您的函数返回void *
的事实意味着有关该指针指向的内容的任何类型信息都将丢失。 You could print one or more bytes starting at that address, but it won't tell you what the original type was. 您可以从该地址开始打印一个或多个字节,但它不会告诉您原始类型是什么。
Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it. 即使该指针有效,您也无法获得足够的信息来强制转换为某些东西,然后将其打印出来。 No information of its size, no information of its internal layout. 没有关于其大小的信息,没有其内部布局的信息。 So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type. 所以,你根本无法打印void *指向的内容,除非你手边有一些手工准备的信息,并强制static_cast为已知类型。 For example: 例如:
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.