c++ - C++ 中的私有(private)成员与临时变量

标签 c++

假设您有以下代码:

int main(int argc, char** argv) {
    Foo f;
    while (true) {
        f.doSomething();
    }
}

以下两种 Foo 实现中哪一种是首选?

解决方案一:

class Foo {
    private:
        void doIt(Bar& data);
    public:
        void doSomething() {
            Bar _data;
            doIt(_data);
        }
};

解决方案 2:

class Foo {
    private:
        Bar _data;
        void doIt(Bar& data);
    public:
        void doSomething() {
            doIt(_data);
        }
};

用简单的英语来说:如果我有一个类,它有一个经常被调用的方法,并且这个方法定义了大量的临时数据(复杂类的一个对象,或者大量简单的对象),应该我将此数据声明为类的私有(private)成员?

一方面,这将节省每次调用时构造、初始化和销毁​​数据所花费的时间,从而提高性能。另一方面,它践踏了“私有(private)成员=对象的状态”原则,并且可能使代码更难理解。

答案是否取决于类 Bar 的大小/复杂性?声明的对象数量如何?在什么时候利大于弊?

最佳答案

从设计的角度来看,如果数据不是对象状态的一部分,则使用临时对象会更干净,并且应该是首选。

在实际分析应用程序之前,切勿根据性能做出设计选择。您可能会发现您最终得到了一个更糟糕的设计,实际上并不比原始设计的性能好多少。

对于所有建议在构建/销毁成本高的情况下重用对象的答案,重要的是要注意,如果您必须从一个调用到另一个调用重用对象,在许多情况下必须将对象重置为有效状态在方法调用之间,这也有成本。在许多此类情况下,重置成本可与 build /破坏相媲美。

如果您不在调用之间重置对象状态,则这两种解决方案可能会产生不同的结果,因为在第一次调用中,参数将被初始化,并且方法调用之间的状态可能会有所不同。

线程安全对这个决定也有很大的影响。函数内的自动变量是在每个线程的堆栈中创建的,因此本质上是线程安全的。任何推送这些局部变量以便它可以在不同调用之间重用的优化都会使线程安全复杂化,甚至可能因争用而导致性能下降,这会恶化整体性能。

最后,如果你想在方法调用之间保留对象,我仍然不会使它成为类的私有(private)成员(它不是类的一部分),而是一个实现细节(静态函数变量,未命名的全局变量)实现 doOperation 的编译单元中的命名空间,PIMPL 的成员...[前 2 个共享所有对象的数据,而后者仅共享同一对象中的所有调用])你的类的用户不关心如何你解决问题(只要你安全地做,并记录该类不是线程安全的)。

// foo.h
class Foo {
public:
   void doOperation();
private:
   void doIt( Bar& data );
};

// foo.cpp
void Foo::doOperation()
{
   static Bar reusable_data;
   doIt( reusable_data );
}

// else foo.cpp
namespace {
  Bar reusable_global_data;
}
void Foo::doOperation()
{
   doIt( reusable_global_data );
}

// pimpl foo.h
class Foo {
public:
   void doOperation();
private:
   class impl_t;
   boost::scoped_ptr<impl_t> impl;
};

// foo.cpp
class Foo::impl_t {
private:
   Bar reusable;
public:
   void doIt(); // uses this->reusable instead of argument
};

void Foo::doOperation() {
   impl->doIt();
}

关于c++ - C++ 中的私有(private)成员与临时变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1311321/

相关文章:

c++:数组,初始化程序太多

c++ - itk 3.20.1 处理器亲和性

c++ - 默认模板参数 : Why does the compiler complain about not specifying template argument?

c++ - 32 位程序无法捕获在 32 位进程上进行的击键,但能够捕获在 64 位进程上进行的击键

c++ - CMake 删除包含目录

c++ - 如何创建自定义的shared_ptr?

c++ - 模板类重载赋值运算符自赋值测试VC++ Express 2010报错

c++: long long int 不会写入文件

C++ winsock 错误

c++ - 嵌套的命名空间和不明确的符号