是否可以在不使用指针的情况下将变量的范围扩展到if语句之外?

时间:2015-09-21 08:59:44

标签: c++ if-statement scope stack

我有一个简单的Trace类,用于记录进入和退出方法:

#include <iostream>

class Trace
{
public:
    Trace()   {std::cout << "Enter" << std::endl;}

    ~Trace()
    {
        std::cout << "Exit" << std::endl;    
    }
};

void foo()
{
    Trace trace;
    std::cout << "foo..." << std::endl;    
}

int main()
{
    foo();
    return 0;
}

输出:

  

输入
  烟草工业
  退出

现在我希望能够启用/禁用跟踪。所以我会做这样的事情:

#include <iostream>

class Trace
{
public:
    Trace()   {std::cout << "Enter" << std::endl;}

    ~Trace()
    {
        std::cout << "Exit" << std::endl;    
    }
    static bool enabled;
};
bool Trace::enabled = false;

void foo()
{
    if(Trace::enabled)
        Trace trace;
    std::cout << "foo..." << std::endl;    
}

int main()
{
    Trace::enabled = true;
    foo();
    return 0;
}

问题是现在trace实例的范围限定为if statement,因此产生了以下输出:

  

输入
  退出
  FOO ...

有没有办法在后一种情况下获得正确的输出,而不使用智能指针?如果禁用跟踪,我希望尽可能减少开销。

P.S。请注意,我的真实世界Trace课程包含更多行,而不仅仅是“输入”和“退出”。

P.S.2 由于性能方面的考虑,如果禁用跟踪,我不希望在堆栈上创建trace实例。

6 个答案:

答案 0 :(得分:4)

  

有没有办法在后一种情况下获得正确的输出,而不使用智能指针?如果禁用跟踪,我希望尽可能减少开销。

现代编译器完全优化简单的智能指针。你应该随意使用RAII和智能指针,这在你的代码中是有意义的。编码干净清晰,避免像这样的微观优化,因为它们几乎从不帮助并经常使事情变得更糟。

答案 1 :(得分:2)

为什么不在Trace构造函数和析构函数中启用测试?

答案 2 :(得分:1)

将您的Trace课改写为

class Trace
{
public:
    Trace()   
    {
        if(Trace::enabled)
            std::cout << "Enter" << std::endl;
    }

    ~Trace()
    {
        if(Trace::enabled)
            std::cout << "Exit" << std::endl;    
    }
    static bool enabled;
};
bool Trace::enabled = false;

只创建没有if的变量:

void foo()
{
    Trace trace;
    std::cout << "foo..." << std::endl;    
}

答案 3 :(得分:1)

除了将启用跟踪的检查放入Trace类的建议之外,还有Tom already suggested

  

是否可以在不使用指针的情况下将变量的范围扩展到if语句之外?

你不应该试试这个。即使使用指针,也无法扩展变量的范围限制。 (好吧,只是为了记录,在if条件中声明的变量的范围也包括else子句,因此也链接else if s。)

更新:关于跟踪类方法的个人想法

即使我认为这种追踪助手

class Trace
{
public:
    Trace(const char* scope): m_scope(scope) { 
        out("enter "); 
    }
    ~Trace() { 
        out("leave "); 
    } 
    const char* m_scope;
    static void out(const char* s) {
        if (enabled) {
            std::cout << s << m_scope << std::endl;    
        }
    }
    static bool enabled;
};  
bool Trace::enabled = false;

对于跟踪程序的控制流似乎很方便,如果发生一些异常,您可能更愿意错过leave跟踪输出。正如我在用这种方法试验一段时间后发现的那样,最好添加普通的跟踪命令。

答案 4 :(得分:1)

放置在堆栈上的对象具有代码,用于将它们放置在编译器在编译时创建的位置。因此,确保不在堆栈上创建对象的唯一方法是在编译时执行此操作。在运行时无法实现这一目标。

现在假设您确实需要优化跟踪对象(您已经对程序进行了分析),实现所需内容的一种方法是使用宏(由前处理器评估)汇编) - 类似于:

  #define TRACE_ON  // comment this to disable Trace

  #ifdef TRACE_ON       
    #define TRACE() Trace trace
  #else       
    #define TRACE()   
  #endif

然后像:

一样使用它
void foo()
{
    TRACE();
    std::cout << "foo..." << std::endl;    
}

答案 5 :(得分:0)

你想要这样的东西:

public void deleteModel() {
        try {
            service.deleteOemModel(selectedModel.getId());
            models= service.getOemModels();
        } ...
    }