【问题标题】:Check in constructor vs. set function签入构造函数与设置函数
【发布时间】:2017-02-14 21:27:41
【问题描述】:

这是一个非常简单的问题。假设我有一堂课

class A
{
public:
  A(int);
  void setA(int);
private:
  int a;
};

实施

A::A(int a_) : a(a_) { }
void A::setA(int a_) { a = a_; }

假设我想避免使用a = 0,但我不想抛出异常,我只想在这种情况下使用a = 1 保留一个有效对象(现在为什么不重要) .

然后我可以在构造函数和setA中添加一个if语句来检查参数是否为0,在这种情况下将其设置为1。从概念上讲,这告诉我在这种情况下我应该更改构造函数,而不是在那里初始化a,我应该在构造函数中调用setA。这样,检查的代码只写一次(请记住,这是一个简单的情况,但在其他情况下验证可能会更复杂)。

现在,这种方法涉及在构造函数中进行额外的函数调用。两次编写验证代码效率更高吗?如果setA 只是偶尔使用会怎样?

【问题讨论】:

  • 无论如何都可能被内联,将其添加到setA 并在构造函数中调用setA。不要再担心这些(似乎是但实际上不是)性能差异。编写干净的代码。优化器将为您完成剩下的工作。
  • 参数不用改名:A::A(int a) : a(a) { }就可以了。
  • @nwp 哇,我不知道。我本来想问一个语言律师的问题,想知道这是什么时候发生的,但显然这已经有一段时间了:stackoverflow.com/q/6185020/2642059
  • @JonathanMee 在每个标准中总是允许的:)
  • @GillBates 我已经利用它两次了。我的代码突然感觉如此精明。

标签: c++ validation constructor


【解决方案1】:

我同意您防止代码重复的热情。小心落水,1-liner 可能落水了。

如果您要进行检查,您应该使用实现文件函数或privatestatic 方法来执行此操作:

int preventZero(const int a_) { return a_ == 0 ? 1 : a_; }

然后你可以在你的实现中使用它,如下所示:

A::A(int a_) : a(preventZero(a_)) { }
void A::setA(int a_) { a = preventZero(a_); }

【讨论】:

    【解决方案2】:

    在构造函数中调用 setter 肯定会更好,因为代码重复是邪恶的。您也可以将其内联以确保不会浪费 CPU 周期,但我认为这是一个过早的优化。

    【讨论】:

    • 现代编译器不听inline
    • 有编译器特定的属性来强制内联 AFAIK,比如 __forceinline for VS
    • @GillBates 除了使您的代码不可移植之外,__forceinline 告诉编译器忽略它是更好的判断并使用您的。请不要使用这样的__forceinline
    猜你喜欢
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多