假设我有这段代码:
class MyClass
{
public:
void SomeFunction()
{
// Find somehow if this is first, second, or third call of a function in a main loop
// If the function is called first time create new variables that will be used just for this function call
}
};
MyClass myClassObject;
int main()
{
myClassObject.SomeFunction(); // First call
myClassObject.SomeFunction(); // Second call
myClassObject.SomeFunction(); // Third call
}
我如何知道内部功能是多少通话? 请注意,我可能会在代码中放置100个函数调用。此外,这应该适用于Windows上的Visual Studio和Mac上的Clang。
我有一个解决方法:
void SomeFunction(const char* indetifier = "address")
{
CheckAddress(indetifier); // This will check if address is stored. If it is not, create variables, if it is, if addresses matches use variables that are tied to that address.
}
我尝试不将新字符串分配给“indetifier”并让它使用默认字符串(“address”)。这当然没有用,因为编译器会优化“indetifier”,所以我想可能一个解决方案是禁用该变量的优化,但我没有,因为应该有一些更优雅的解决方案。
还有一件事出现在我脑海中,也许我可以强制内联一个函数,然后得到它的地址,但这也像坏的解决方法一样。
我还可以为每个调用创建新类,但我想避免这种情况,因为会有很多函数调用,我不想考虑100个不同的名称。
如果有一种方法只在第一次调用时创建类对象,那就太棒了。
我希望你能理解我想要的东西,对不起,如果因为我是初学者而没有那么清楚......:D
修改
我不能在类中使用static作为变量,因为我正在开发的软件是一个可以在主机内部加载多个实例的插件,这可能会搞乱变量。我已经测试了静态变量,如果我在任何地方创建“静态int值”,并在插件的一个实例中写入一些内容,这个“值”将针对插件的所有实例进行更新,这不是我想要的。
答案 0 :(得分:0)
在C ++中,您可以在局部变量上下文中使用static
关键字在第一次调用时仅创建一次对象:
#include <iostream>
struct MyObject {
MyObject() {
std::cout << "Creating instance " << this << "\n";
};
};
void foo() {
static MyObject my_instance;
std::cout << "... inside function foo ...\n";
}
int main(int argc, const char *argv[]) {
std::cout << "About to call foo...\n";
foo();
std::cout << "... second call ...\n";
foo();
std::cout << "... third call ...\n";
foo();
return 0;
}
使用上面的代码,您会注意到,在第一次调用MyObject
时,只会在对象foo
上创建。
请注意,如果您的函数是模板,那么对于模板的每个实例化,您将获得另一个不同的静态变量。例如:
template<int N>
void foo() {
static MyObject my_instance;
std::cout << "... inside function foo ...\n";
}
对foo<1>()
的所有调用都将使用相同的变量,但调用foo<2>()
将访问函数的另一个副本(函数模板的另一个实例),它将具有自己的不同静态变量在第一次调用foo<2>()
时创建。当程序终止时,所有已初始化的静态变量将在main
结束后销毁。
答案 1 :(得分:0)
void SomeFunction() { // Find somehow if this is first, second, or third call of a function in a main loop // If the function is called first time create new variables that will be used just for this function call }
如果要跟踪每个对象的第一个调用,那么您需要一个成员变量来跟踪为该对象调用SomeFuntion
的次数。
如果要独立于对象跟踪第一个调用,则可以使用static
函数变量来跟踪为该对象调用SomeFuntion
的次数。
答案 2 :(得分:0)
我不能在类中使用静态变量,因为我正在开发的软件是一个插件,可能在主机内部加载了多个实例,这可能会搞乱变量。我已经测试了静态变量,如果我创建了例如&#34; static int value&#34;在任何地方,并在插件的一个实例中写一些东西,这个&#34;值&#34;将针对插件的所有实例进行更新,这不是我想要的。
那么制作一个非静态计数器?
class MyClass {
int count;
public:
MyClass () : count(0) { }
void SomeFunction () {
++ count;
// do stuff with 'count'
}
};
MyClass myClassObject;
int main () {
myClassObject.SomeFunction(); // First call
myClassObject.SomeFunction(); // Second call
myClassObject.SomeFunction(); // Third call
}
或者只是将其作为参数传递......
class MyClass {
public:
void SomeFunction (int count) {
// do stuff with 'count'
}
};
MyClass myClassObject;
int main () {
myClassObject.SomeFunction(1); // First call
myClassObject.SomeFunction(2); // Second call
myClassObject.SomeFunction(3); // Third call
}
但我真的很想知道你实际上想要做什么,我强烈建议你坐下来重新思考这一切,因为这里有许多危险信号/混淆点...... / p>
答案 3 :(得分:0)
如果您只想检查是否是第一个电话,则可以向bool SomeFunction_first_call;
添加MyClass
,以充当标志。构造函数将bool
设置为true
。 MyClass::SomeFunction()
使用条件检查if (SomeFunction_first_call) /* ... */
来确定它是否是第一次调用,如下所示:
class MyClass
{
bool SomeFunction_first_call;
public:
MyClass() : SomeFunction_first_call(true) {}
void SomeFunction()
{
if (SomeFunction_first_call)
{
// This code only executes on first call.
do_something();
// Successfully handled first call, set flag to false.
SomeFunction_first_call = false;
}
// This code always executes.
do_something();
}
};
同样,如果您只关注前HOWEVER_MANY_CALLS
次来电,其中HOWEVER_MANY_CALLS
是一个数字,您可以使用以下内容:
#include <cstdint>
class MyClass
{
uint8_t SomeFunction_calls;
public:
MyClass() : SomeFunction_calls(0) {}
void SomeFunction()
{
// This segment will be executed until (SomeFunction_calls == HOWEVER_MANY_CALLS).
// After this, the segment will be skipped, and the counter will no longer increment.
if (SomeFunction_calls < HOWEVER_MANY_CALLS)
{
// This code only executes on first HOWEVER_MANY_CALLS calls.
do_something();
// Increment counter.
++SomeFunction_calls;
}
// This code always executes.
do_something();
}
};
确保使用适当签名的变量来表示需要特殊处理的呼叫数量(例如{0}为0..255,uint8_t
为256..65,535等)。如果uint16_t
的不同实例需要跟踪不同数量的调用,则使用非类型模板参数来指示此情况,并可选地使用默认MyClass
来指示计数器应该采用何种类型是
typename
在这种情况下,#include <cstdint>
template<uint64_t N, typename T = uint64_t>
class MyClass {
T SomeFunction_calls;
...
void SomeFunction()
{
if (SomeFunction_calls < N) {
...
}
...
}
};
将对MyClass<4>
的前4个电话进行特殊处理,SomeFunction()
将对前4,444,444,444,444,444,444电话进行特殊处理,依此类推。计数器将默认为MyClass<4444444444444444444>
,因为它应足够大以容纳该值;当只有少数呼叫需要特殊处理时,您可以指定较小的类型,例如uint64_t
或MyClass<4, uint8_t>
。