C++ 中的私有成员与临时变量

2024-02-24

假设您有以下代码:

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);
        }
};

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

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

答案是否取决于 Bar 类的大小/复杂性?声明的对象数量怎么样?什么时候好处会超过坏处?


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

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

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

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

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

最后,如果您想在方法调用之间保留对象,我仍然不会将其设为类的私有成员(它不是类的一部分),而是将其设为实现细节(静态函数变量,在未命名命名空间中全局)实现 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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中的私有成员与临时变量 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • json.net自定义jobject反序列化

    我正在尝试使用 JsonConvert DeserializeObject string 将字符串反序列化为可与动态一起使用的 jobject 来动态访问 json 文档 但是我想避免知道文档的大小写 以便我可以输入 dynamic doc
  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 从代码中,如何创建对存储在附加属性中的对象的属性的绑定?

    我们有一个继承的附加属性来存储一个对象 在可视化树的更下方 我们希望从代码绑定到该对象的属性 通常我们像这样构建绑定的路径部分 var someBinding new Binding Path new PropertyPath Attach
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 使用 LINQ 更新 IEnumerable 对象的简单方法

    假设我有一个这样的业务对象 class Employee public string name public int id public string desgination public int grade List
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 通过 Tab 键浏览 XML 文档字段

    In VB NET you can move through the fields in the XML member documentation with the Tab key 这在 C 中不起作用 还有其他方法吗 除了用鼠标将光标放在
  • 使用未分配的局部变量

    我遇到了一个错误 尽管声明了变量 failturetext 和 userName 错误仍然出现 谁能帮帮我吗 Use of Unassigned local variable FailureText Use of Unassigned lo

随机推荐

  • Prolog,在列表中找到最小值

    简而言之 如何找到列表中的最小值 感谢卡雷尔的建议 很长的故事 我在 amzi prolog 中创建了一个加权图 并给定 2 个节点 我能够检索路径列表 但是 我需要找到该路径中的最小值 但无法遍历列表来执行此操作 我可以就如何确定列表中的
  • 使用 Flask 作为文件上传的传递代理?

    它用于应用程序引擎的 blobstore 因为它的上传接口每次都会生成一个临时端点 我想消除前端的复杂性 Flask 会接受 post 请求并将其转发到 blobstore 指定的端点 性能和流量成本根本不是问题 有人可以推荐一种最直接的实
  • Array(x) 是一种什么样的 ruby​​ 方法调用

    以下内容的含义是什么 其语法的 Ruby 文档在哪里 Array phrases 我在此处浏览 Rails 源代码时发现 File actionpack lib action view helpers text helper rb line
  • 将代码从 MySQL 更改为 PDO

    我制作了一个使用 MySQL 语法编写的 CMS 脚本 我想用 PDO 语法替换 MySQL 语法 有人可以吗帮我做 and 向我解释一下该怎么做 这是脚本中的代码
  • 如何在 Xcode 7 中使用 xcodebuild 和手表扩展

    我们的命令以前是这样的 xcodebuild configuration Release target xxx sdk iphoneos9 0 scheme xxx archive 现在在 Xcode 7 中 我们收到此错误 Build s
  • 通过 Linux FrameBuffer 将像素绘制到屏幕

    最近 我被一个奇怪的想法所震惊 从 dev urandom 获取输入 将相关字符转换为随机整数 然后使用这些整数作为像素的 rgb x y 值来绘制到屏幕上 我做了一些研究 在 StackOverflow 和其他地方 许多人建议您可以直接写
  • 使用 iText 更改 PDF Producer 属性

    是否可以使用 iText 更改 PDF 文档的现有属性 我试过这个 Map
  • Google 登录错误 12500

    我正在尝试将 Google Sign In 集成到我的应用程序中 我没有后端服务器 我只是将登录的 Google 帐户的详细信息获取到我的应用程序 我首先尝试使用Google 登录示例 https github com googlesamp
  • 转义特殊字符 (ø, æ) 以在 url 内使用

    我尝试在 iOS 应用程序中显示带有 URL 源的图像 但它没有显示 图像的 url 是实时示例路径 使用以下 Objective C 代码转义该字符串时 NSString url NSString CFURLCreateStringByA
  • 检查指定名称的屏幕是否存在

    我制作了一个 bash 文件 它在独立的屏幕中启动另一个具有唯一名称的 bash 文件 我需要确保该内部 bash 文件的一个实例在任何一个时间点都在运行 为此 我希望在尝试创建父 bash 文件之前检查该名称的屏幕是否存在 有没有办法做到
  • 正则表达式 $1、$2 等

    我一直在尝试在 PHP 中进行一些正则表达式操作 但我在这方面不是很熟练 似乎当我在字符串上使用像 preg replace 这样的正则表达式函数时 我可以通过某种名为 1 2 等的变量访问正则表达式替换的字符串 这叫什么 我该如何使用它
  • 使 CSS 工具提示跟随光标

    我正在创建一个基于 CSS 的工具提示 该工具提示中将包含大量内容 而不是处于静态位置 我想知道是否有一种简单的方法可以使其在将鼠标悬停在链接上时跟随光标 这是基于 CSS 的工具提示示例 div class couponcode Firs
  • Flux/React Complex 可重复使用组件

    我想做这样的事情 var App React createClass render function return
  • 如何在Django中获取所有POST请求值?

    有没有办法从 Django 的请求中获取所有表单名称
  • 为什么 TextRenderer.MeasureText 无法正常工作?

    我想在给定一定宽度的可用画布的情况下测量文本的高度 我传入的文本非常长 我知道会换行 为此 我呼吁如下 using System Windows Forms string text Really really long text that
  • 如何在使用清单 v3 制作的 Chrome 扩展中使用 Web 套接字显示实时数据?

    我正在开发一个简单的扩展 我想在其中展示RealTime通过网络套接字连接从我的服务器发送的数据 我正在使用 chrome 的清单 v3 来实现这一点 我尝试通过网络套接字连接我的扩展background js它作为 Service Wor
  • std::map 键的要求(设计决策)

    当我做一个std map
  • 协调 CACurrentMediaTime() 和 deviceCurrentTime

    我正在尝试同步几个CABasicAnimations with AVAudioPlayer 我的问题是CABasicAnimation uses CACurrentMediaTime 作为安排动画时的参考点AVAudioPlayer use
  • Python argparse:有没有办法在 nargs 中指定范围?

    我有一个可选参数 它支持参数列表本身 我的意思是 它应该支持 f 1 2 f 1 2 3 but not f 1 f 1 2 3 4 有没有办法在 argparse 中强制执行此操作 现在我使用 nargs 然后检查列表长度 Edit 根据
  • C++ 中的私有成员与临时变量

    假设您有以下代码 int main int argc char argv Foo f while true f doSomething 以下两种 Foo 实现中哪一个是首选 解决方案一 class Foo private void doIt