Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中检测编译时的重复工作+;代码 让我们考虑下面的代码: struct Foo { Foo(Bar b1, Bar b2) : b1(b1), b2(b2) {} void work() { b1.work(); b2.work(); //something } Bar& b1; Bar& b2; }; struct Bar { void work() { /* something */ } }; int main() { Bar a, b; a.work(); //something... Foo c(a,b); c.work(); //something... }_C++_Metaprogramming - Fatal编程技术网

C++ 在C+中检测编译时的重复工作+;代码 让我们考虑下面的代码: struct Foo { Foo(Bar b1, Bar b2) : b1(b1), b2(b2) {} void work() { b1.work(); b2.work(); //something } Bar& b1; Bar& b2; }; struct Bar { void work() { /* something */ } }; int main() { Bar a, b; a.work(); //something... Foo c(a,b); c.work(); //something... }

C++ 在C+中检测编译时的重复工作+;代码 让我们考虑下面的代码: struct Foo { Foo(Bar b1, Bar b2) : b1(b1), b2(b2) {} void work() { b1.work(); b2.work(); //something } Bar& b1; Bar& b2; }; struct Bar { void work() { /* something */ } }; int main() { Bar a, b; a.work(); //something... Foo c(a,b); c.work(); //something... },c++,metaprogramming,C++,Metaprogramming,按照我编写(或打算编写)的方式,a.work()将执行两次。但是,让我们假设,我,正如程序员所知道的,执行它两次是对执行时间的浪费,让我们假设这是一个更复杂的软件的一部分,在这个软件中,手动跟踪哪些工作是完成的,哪些工作没有完成太麻烦了 显然,我可以在Bar中存储一些布尔标志,每次都检查工作是否已经完成,但我想知道,是否有某种方法可以在编译时捕捉到它。因为在编译时,已经很清楚工作已经完成了。不,不太清楚 编译器能够进行一些静态分析,如果您可以要求它诊断这种情况,在一些简单的情况下,它可能能够这样

按照我编写(或打算编写)的方式,a.work()将执行两次。但是,让我们假设,我,正如程序员所知道的,执行它两次是对执行时间的浪费,让我们假设这是一个更复杂的软件的一部分,在这个软件中,手动跟踪哪些工作是完成的,哪些工作没有完成太麻烦了

显然,我可以在Bar中存储一些布尔标志,每次都检查工作是否已经完成,但我想知道,是否有某种方法可以在编译时捕捉到它。因为在编译时,已经很清楚工作已经完成了。

不,不太清楚

编译器能够进行一些静态分析,如果您可以要求它诊断这种情况,在一些简单的情况下,它可能能够这样做。但是一旦你有了一个非平凡的流程(例如,运行时
if
条件),它就会很快离开窗口。这可能是没有人为编译器创建这样一个可编程特性的部分原因:高复杂性,可忽略不计的实用性

也许可以对一些第三方静态分析仪进行编程(或创建一个!)来诊断您的简单案例,但同样,对于处理您已经可以用眼睛发现的最琐碎的案例来说,这需要大量的工作

相反,您可以使
work()
发生在
Bar
构造函数中。那么在同一物体上做两次功是不可能的。然而,在一个构造器中执行大量的工作通常是不受欢迎的

我确实会在
栏中保留一个状态标志
,并通过相应地维护该标志的值,从后续的
工作()返回
false
。作为奖励,在返回
false
之前,在函数中粘贴一个断言,以便在测试过程中捕获违规行为

州标志不必是布尔值;它可以是
枚举
。对象中的健壮状态机非常有用


话虽如此,我还是建议您重新审视当前的方法,将对事物的引用传递给对它们起作用的其他事物;这不是一个容易遵循的设计,这只是一个简单的例子,你的设计!您可能希望考虑传递一些单用代理类型。

实际上,在编译时,代码是否执行并不明显。假设您有一个if语句,并在其中调用
a.work()
。编译器如何知道当时是否执行了
a.work()
?正如您所说,不要认为
if
语句非常简单(假设它正在寻找某个外部信号并根据该信号执行代码)。避免这种行为的最好方法是保持布尔值。

另一种方法。在
对象中有一个函数指针,并在
work()
函数中调用
指针
。在构造函数中,将指针定义为实际的功函数。在函数末尾,将指针重新指定为空函数

在这种情况下,第一次执行将完成任务。但是以后的执行将不起任何作用(也不检查
布尔值
标志)


类似上面的内容。

肮脏的方式:预处理器宏定义在
work()内部。
#如果ndef已经完成#定义已经完成(…例程)#endif
@Suthiro如何工作?这是预处理器。@asterswithwings经过再三考虑后,你是对的-它不会,但我认为它可以通过预处理器实现。@Suthiro我不知道你是想诊断/发现第二个呼叫,还是只是默默地将其设为不操作?您的要求是什么?这实际上是一个好主意(假设OP不需要诊断第二个呼叫,只需将其设置为无OP)。虽然它基本上与
bool
的思想相同,只是添加了间接寻址,但您可能是对的,但是在
boolean
情况下,程序每次都会检查布尔值。我知道,检查并不是最糟糕的操作,而且非常琐碎。但是如果问题是不再需要做更多的操作,我认为这是一个很好的例子。谢谢你的想法。但是,如果编译器认为这是合理的,那么编译器就不可能内联实际工作了吗?如果是这样的话,我会更倾向于你的另一个答案,即我应该使用布尔值。正如我在运行时所猜测的,不可能使函数以内联方式编译。如果要将其编译为内联函数,布尔值是解决方案,但如果不需要内联,两者都适用。@arsdever我认为检查
bool
比取消引用指针来调用函数便宜。此外,使用
bool
,您可以用它做其他事情,而如果您想检查“函数是否为空?”则不能检查。但我们都在扯淡;)
struct Bar {
  typedef void (*Bar::fptr_t)();
  Bar() : fptr(actual_work) {}
  void actual_work() {
    /*something*/;
    fptr = &Bar::empty_work;
  }

  void empty_work() {}
  void work() {fptr();}
  fptr_t fptr;
};