在C ++中,我们如何执行以下操作
// fundamental language construct
type name = value ;
// for example
int x = y;
带有功能指针?
typedef (char)(*FP)(unsigned);
// AFAIK not possible in C++
FP x = y ;
我可以使用lambda:
FP x = []( unsigned k) -> char { return char(k); }
但是我不知道如何在没有lambda的情况下执行此操作。有什么想法吗?
答案 0 :(得分:13)
您可以使用auto fptr = &f;
:
public static void test(String a)
{
char[] tochar=a.toCharArray();
int b[]=new int[a.length()];
for(int i=0;i<b.length;i++)
{
b[i]=(int)(tochar[i]);
}
for(int i=0;i<b.length;i++)
System.out.println(b[i]);
}
public static void main (String[] args)
{
test("55354"); }
它跳过了对typedef的需求,并保留了一个不错的语法。
答案 1 :(得分:12)
只要可以编写typedef,就可以使用几乎相同的语法编写不带typedef的变量声明。
示例:
main_window.close()
删除 // typedef
typedef char(*FP)(unsigned);
FP x = y ;
// no typedef
char(*x)(unsigned) = y;
关键字,您将获得一个变量声明。如果需要,可以对其进行拍打。
答案 2 :(得分:6)
它与Lambdas几乎相同,但我认为很难理解:
void my_int_func(int x)
{
std::cout << "ther param is: " << x << std::endl;
}
//
int main(int argc, char *argv[])
{
void (*foo)(int) = my_int_func;
foo(1);
答案 3 :(得分:4)
但是我不知道如何在没有lambda的情况下执行此操作。有什么想法吗?
只使用lambda而不是函数:
typedef char(*FP)(unsigned);
char foo(unsigned){ return 0;}
int main() {
FP x = foo;
}
如果可以更好地使用using
,则函数指针typedef很讨厌:
using FP = char(*)(unsigned);
答案 4 :(得分:2)
好吧...如果您使用的是lambda,则还可以使用auto
,
auto x = foo;
以下是带有static_assert()
的完整编译示例,用于验证获得的类型
#include <type_traits>
char foo (unsigned)
{ return ' '; }
int main ()
{
auto x = foo;
static_assert( std::is_same<decltype(x), char(*)(unsigned)>::value, "!" );
}
将auto
与lambda一起使用,就像将其与FP
一起使用
auto y = []() ->bool { return true; };
导致不同的结果:上方y
的类型是带有operator()
的未命名类,而不是指向该operator()
的函数指针类型。
如果要使用函数指针,则必须使用运算符+
将lambda转换为它,您可以使用以下static_assert()
进行验证
auto y = +[]() ->bool { return true; };
static_assert( std::is_same<decltype(y), bool(*)()>::value, "!" );
答案 5 :(得分:1)
非常感谢大家对有用评论的热烈欢迎。在Reddit上,有人问我同样的问题,用户名为“ TheTiefMaster”,掉了这个“一个衬里”:
// also works as C
char whatever(unsigned k) { return char(k); } char(*F)(unsigned) = whatever;
让我澄清一下:我确实理解这是一行上的两个陈述。而且这里没有类型,只有一个指向同一函数的函数指针。用法:
auto x = whatever(65); // 'A'
auto y = F(66); // 'B'
然后我想出以下内容将对函数定义及其类型进行声明:
// FP is a type of function whoever
char whoever(unsigned k) { return 'A'; } typedef char(*FP)(unsigned) ;
呼叫行为符合预期的人
auto w = whoever(42) ; // 'A'
FP是开始变得有趣的地方。 FP是一种类型,事实证明可以将其转换为该类型。
// using FP as a type
// c++ style type cast
// empty cast returns nullptr
auto fun = FP();
// calling fun() above crashes
// but it is "invocable" as per C++ rules
static_assert(std::is_invocable_v<P2F()>);
将任何参数传递给此强制转换,可以工作并返回非空地址:
// update: this compiles only on MSVC
// and is a bug
auto fun = FP(42);
// type of fun is char (*) (unsigned)
调用此乐趣的结果显然会崩溃:
// reading access violation
fun(123) ;
此强制转换带有任何所需函数的实例,可以起作用:
auto fun = FP(whatever);
// works, obviously
fun(65) ; // 'A'
要使用此知识,我们将使用static_cast安全地转换为我们可以调用的内容。 C ++类型转换过于强制,就像C风格类型转换一样。
// does not compile
// fun is the wrong type and can not be called
auto fun = static_cast<FP>(42);
// does compile, fun is safe to call
auto fun = static_cast<FP>(whatever);
// works, obviously
fun(65) ; // 'A'
这项调查显然还没有结束。我将在其他地方继续进行。
更新:
using FP = char (*)(int) ;
// must not compile, compiles under MSVC
auto oops = FP(42) ;
是MSVC中的错误,我今天报告了它。
答案 6 :(得分:0)
代码:
typedef char(*FP)(int);
FP x = y;
如果y
是捕获变量的lambda表达式,则无法使用当前的C ++编译器进行编译。
// Compiles OK
FP x0 = [](int k) -> char { return char(k); };
// Fails to compile
int i = 123;
FP x1 = [=](int k) -> char { return char(k); };
FP x2 = [=](int k) -> char { return char(k+i); };
FP x3 = [&](int k) -> char { return char(k+i); };
FP x4 = [i](int k) -> char { return char(k+i); };
// error: cannot convert ‘main()::<lambda(int)>’ to ‘FP {aka char (*)(int)}’
// in initialization
之所以无法编译,是因为x1
... x4
的赋值右侧的大小大于FP
的大小。
要使C ++编译器对x1
... x4
进行赋值是有效的,则需要在运行时生成代码。当前的C ++编译器(例如GCC和clang)不支持此功能,主要是因为C ++不是垃圾收集语言,否则会导致内存泄漏。一些垃圾收集的语言实现(例如官方Go编译器的早期版本)通过执行运行时代码生成来支持此类分配。