2

具体来说,我想知道我应该写哪些:

{
    shared_ptr<GuiContextMenu> subMenu = items[j].subMenu.lock();
    if (subMenu)
        subMenu->setVisible(false);
}

或者:

{
    if (items[j].subMenu.lock())
        items[j].subMenu.lock()->setVisible(false);
}

我不需要遵循任何风格准则。优化后,我认为这两种选择都不会影响性能。通常首选的风格是什么,为什么?

编辑: items[j].subMenu 的类型是 boost::weak_ptr。lock() 从中创建一个 shared_ptr 。实际上,上述两个版本在临时 shared_ptr 持续多长时间方面存在模棱两可的差异,因此我将两个示例包装在 { 大括号 } 中以解决其中的歧义。

4

10 回答 10

7

另一种方法:

if(shared_ptr<GuiContextMenu> subMenu = items[j].subMenu.lock()) {
    subMenu->setVisible(false);
}
//subMenu is no longer in scope

我假设subMenu是 a weak_ptr,在这种情况下,您的第二种方法会创建两个临时对象,这可能是也可能不是问题。您的第一个方法将变量添加到比它需要的范围更广的范围内。就个人而言,我尽量避免在if语句中进行赋值,但这是我觉得它比替代方案更有用的少数情况之一。

于 2010-04-27T22:02:55.207 回答
4

这种特殊情况下,您确实应该使用带有临时变量的版本。原因不是性能,而是正确性 - 基本上,您不能保证两个x.lock()调用返回相同的值(例如,如果另一个线程在两个调用之间释放对象的最后一个强引用)。通过在临时变量中保存强引用,您可以确保它不会消失。

除此之外:

  • 编译器通常无法优化函数调用,除非它们可以证明没有副作用(这很难做到,但属性可能会有所帮助)或内联。在这种情况下,调用有副作用。

  • 使用临时程序可以使程序更短、更易读和更易于维护(例如,如果出现错误,您可以在一个地方修复它)

于 2010-04-27T22:15:58.930 回答
2

我认为您对优化后任何一种选择都没有什么不同是正确的。

就个人而言,如果它使代码更具可读性,我会声明一个新变量,例如当您链接调用或将函数调用放入函数调用时。只要它是可维护的并且代码在没有速度差异的情况下达到相同的效果,这一切都归结为可读的代码。

编辑:

mmyers 买了一个很好的评论。是的,要小心调用lock()两次,而不是只调用一次。根据您的实施,它们将产生不同的效果。

于 2010-04-27T21:34:39.267 回答
1

选择基本上取决于您,但您应该注意的基本事项是可维护性。

于 2010-04-27T21:53:31.240 回答
1

在这个具体的例子中,我认为这取决于做什么lock()。功能贵吗?每次调用函数时它会返回不同的东西吗(它是否第一次返回指针而第二次返回 NULL)?是否有另一个线程可以在两个调用之间交错运行lock()

对于此示例,您需要了解代码的行为lock()和其余代码才能做出明智的决定。

于 2010-04-27T21:55:46.013 回答
1

当返回值不是布尔值时,将其分配给中间变量通常可以简化调试。例如,如果您跳过以下内容:

if( fn() > 0 ) ...

事后您将知道的是该函数返回的值要么小于零,要么为零或更大。即使返回值不正确,代码似乎仍然可以工作。将它分配给可以在调试器中检查的变量将允许您确定返回值是否是预期的。

当 return 为 boolean 时,实际值完全被代码流隐含,因此不太重要;但是,在代码维护下,您可能会发现稍后您需要该结果,因此您可能决定在任何情况下都养成习惯。

即使返回值是布尔值,另一个需要考虑的问题是函数是否需要副作用,以及这是否会受到短路评估的影响。例如在声明中:

if( isValid && fn() ) ...

该函数将永远不会被调用 isValid 为假。

粗心的程序员(通常是经验不足的程序员承担维护任务)在维护时可能会破坏代码的情况很多,最好避免。

于 2010-04-27T22:02:42.697 回答
0

大多数时候我更喜欢第一个,因为它使代码更清晰易读,因此不易出错。例如,您忘记了第二个示例的括号:) 在这种情况下,实际上,我可能会做您在第二个示例中所做的事情,但是如果我需要多次使用该子菜单,我会选择第一个使代码更易于阅读。至于性能,我认为任何理智的编译器都可以对其进行优化(这可能就是您没有看到性能差异的原因)。

此外,正如 mmyers 指出的那样,这也取决于 lock() 的作用。一般来说,如果它是一个简单的 getter 方法或类似的东西,你会没事的。

于 2010-04-27T21:35:50.357 回答
0

无论您喜欢什么。对我来说,这取决于我会用多少;对于两行,我可能只写两次,而如果我更多地使用它,我会创建一个变量。但是,您最有可能必须维护此代码并继续查看它,因此请使用适合您的任何内容。当然,如果您所在的公司有编码指南,请遵循它。

于 2010-04-27T21:42:35.800 回答
0

我认为首选样式是您认为使您的代码更具可读性和可维护性的任何样式。如果你是一个多人的团队,唯一的另一个考虑是每个人都采用相同的风格通常是一个好主意,同样是为了可读性和易于维护。

于 2010-04-27T22:09:03.817 回答
0

在这种情况下,我认为你应该使用临时的。即使您知道 .lock() 的实现很便宜,也可以改变。如果您不需要调用 lock() 两次,请不要。这里的价值在于它将您的代码与 lock() 的实现分离。这通常是一件好事。

于 2010-04-27T22:20:05.103 回答