简体   繁体   English

C ++中的void指针

[英]void pointers in C++

I saw this example on a website, and the websites mentions:- "One of its uses (void pointers) may be to pass generic parameters to a function" 我在一个网站上看到了这个例子,网站提到: - “它的一个用途(void指针)可能是将通用参数传递给一个函数”

// increaser
#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << endl;
  return 0;
}

wouldn't it be simpler to write code like the following? 编写如下代码会不会更简单?

void increaseChar (char* charData)
{
    ++(*charData);
}

void increaseInt (int* intData)
{
    ++(*intData);
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increaseChar (&a);
  increaseInt (&b);
  cout << a << ", " << b << endl;
  string str;
  cin >> str;
  return 0;
}

It is less code, and really straightforward. 代码更少,而且非常简单。 And in the first code I had to send the size of the data type here I don't! 在第一个代码中,我不得不在这里发送数据类型的大小!

It would be best to make the function type safe and generic. 最好使函数类型安全且通用。 It would also be best to take the argument by reference instead of by pointer: 最好通过引用而不是指针来获取参数:

template <typename T>
void increment(T& data) {
    ++data;
}

void* should be avoided wherever possible in C++, because templates and inheritance provide type-safe alternatives. 在C ++中应尽可能避免使用void* ,因为模板和继承提供了类型安全的替代方法。

Your code is definitely preferable. 你的代码绝对是可取的。 void* loses any pretense to type safety, your typesafe overloads are much better. void*失去任何类型安全的假装,你的类型安全过载要好得多。 Good instincts. 良好的直觉。

To support more types generically in C++ you would define a class or function template, not use void* . 要在C ++中一般支持更多类型,您可以定义类或函数模板,而不是使用void* References would be preferable to pointers, but your code could be changed to this: 引用优于指针,但您的代码可以更改为:

template <class T> T increase(T* value)
{
    return ++(*value);
}

int main(int argc, char* argv[])
{
    int i(0);
    increase<int>(&i);

    char c(0);
    increase<char>(&c);

    return 0;
}

What's the website, as a matter of interest? 作为一个有趣的问题,该网站是什么?

Your solution works only for int or char. 您的解决方案仅适用于int或char。 Consider the situation you want to go through array of some custom type( struct, for example ). 考虑一下你想要通过一些自定义类型(例如struct)的数组的情况。 In your code you will need to add a method to do that, however in the example above no line of could should be added to get the work example. 在您的代码中,您需要添加一个方法来执行此操作,但是在上面的示例中,不应添加任何行来获取工作示例。

"One of its uses (void pointers) may be to pass generic parameters to a function" “它的一个用途(void指针)可能是将泛型参数传递给函数”

Not a good-style use, to be certain. 肯定不是一种好的用途。 Passing generic parameters to functions is done by: 将通用参数传递给函数的方法是:

a) templates (and possibly template specializations) which allows to write safe code, a)允许编写安全代码的模板(以及可能的模板特化),
b) OOP approaches. b) OOP方法。

I like your second increaseInt and increaseChar solution better. 我喜欢你的第二次increaseIntincreaseChar更好的解决方案。 You can rewrite it as: 您可以将其重写为:

template<typename T>
void increase(T* pData)
{
    ++(*pData);
}

It will work for any type which supports ++ and be safe. 它适用于任何支持++并且安全的类型。


Sometimes you'd still need a void pointer as a "generic parameter" - for example when using the popular pthread library. 有时你仍然需要一个void指针作为“通用参数” - 例如在使用流行的pthread库时。 When you spawn a thread, you may send it some arbitrary data (of any type you want), and it's done using - well - a void* pointer. 当你产生一个线程时,你可以发送一些任意数据(你想要的任何类型),并且使用 - well - 一个void*指针完成它。 The pthread library is in C not C++, which may be one of the reasons, but you might want to interface with it from C++ and this will indeed require you to use the void* pointer as a "generic type". pthread库是C而不是C ++,这可能是原因之一,但您可能希望从C ++接口,这确实需要您将void*指针用作“泛型类型”。 Not much harm done there, though; 但是,那里没有太大的伤害; just remember that for everyday coding there are more elegant solutions. 请记住,对于日常编码,有更优雅的解决方案。

Actually I think the example is quite bad. 其实我觉得这个例子很糟糕。 One of the canonical examples would be the C library's qsort , where you pass in void* as well as a function which interprets the data. 其中一个规范示例是C库的qsort ,您可以在其中传递void* 以及解释数据的函数。

However, in C++, there are better mechanisms available which are less likely to silently malfunction. 但是,在C ++中,有更好的机制可用于静默故障。

Hence, the use of void* to pass generic data around should probably be limited to 因此,使用void*传递通用数据可能应该限于

  1. instances where code bloat is important, and 代码膨胀很重要的实例
  2. code which interacts with other language, in particular C. 与其他语言交互的代码,特别是C.

When you are programming C (not C++) void* is you only way to do something generic. 当你编程C(而不是C ++)时,void *只是你做一些通用的方法。 Nevertheless the example is terrible. 然而这个例子很可怕。 This scheme is often used for callback mechanics, where you pass a function pointer and a void*. 此方案通常用于回调机制,您可以在其中传递函数指针和void *。 For example: 例如:

void handle_crash(void* data)
{
    Log* log = (Log*)data;
    log->print("We crashed.");
}

Log log;
set_crash_handler(&handle_crash, &log);

You will see this often on C frameworks such as libxml2 or spidermonkey. 您将经常在C框架上看到这一点,例如libxml2或spidermonkey。 In the case of C this is the only thing there is to accomplish it. 在C的情况下,这是唯一可以实现它的东西。 It is not a very robust solution. 它不是一个非常强大的解决方案。

In case you are working with C++ you have more options. 如果您使用的是C ++,则可以选择更多选项。 Basic generic programming can be done with templates or overloading as mentioned in other answers. 基本通用编程可以使用模板或重载完成,如其他答案中所述。 In case you need solid callback mechanic you might want to look into libsigc++ or other "signals and slots" frameworks. 如果您需要可靠的回调机制,您可能需要查看libsigc ++或其他“信号和插槽”框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM