如何防止意外地在非常量对象上调用变异函数?

2024-04-23

假设我们有一个 myType 类型的对象 obj,并且我们希望将其传递给函数 Foo,该函数返回一些有关 obj 的有价值的信息。函数 Bar 是声明 obj 的地方,也是从中调用 Foo 的地方,如下所示:

void Bar ()
{

myType obj; //default constructor

string valuableInfo = Foo(obj); 

//do other stuff
//...

} //end of Bar()

当然,这段代码并没有过多说明 Foo 是否将 obj 作为引用或值,以及 Foo 是否以任何方式修改 obj。

当然,如果 Food 将对象作为值或 const 引用,我们就不会有任何问题。

string Foo (const myType & input); //this is fine 
string Foo (myType input); //so is this

但我们不能保证这一点!函数签名很可能是

string Foo (myType & input); //asking for trouble!!

但是检查我们想要传递 obj 的每个函数的签名非常不方便,那么我们如何指定我们只想将对象传递给承诺不修改它的函数呢?

当然,一种方法是将 obj 声明为 const,但这种方法的问题是我们失去了灵活性。如果我们想在调用 Foo(obj) 后修改 Bar() 中的 obj 该怎么办?

void Bar ()
{

const myType obj; //default constructor

string valuableInfo = Foo(obj); //compiler will complain if Foo's signature doesnt match

//we can't modify obj here :(
//...

} //end of Bar()

显而易见但糟糕的解决方案是这样做:

void Bar ()
{

myType obj; //default constructor

const myType immutableObj {obj}; //copy ctr call
//this is expensive and not recommended if obj is big! want to avoid

string valuableInfo = Foo(immutableObj); //will get the valuable Info risk free
// compiler will complain if Foo has inappropriate signature

//do other stuff
//...

} //end of Bar()

那么这里最好的解决方案是什么?有没有办法静态断言 Foo 对我们传入的对象是非侵入性的?我们可以暂时将 obj 设置为 const (无需创建新的 const 对象)或达到此效果吗?


In C++17 http://en.cppreference.com/w/cpp/utility/as_const, 谢谢P0007R1 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0007r1.html:

foo(std::as_const(obj));

在 C++17 之前,如果您发现自己需要经常这样做,那么自己编写一个帮助器就很简单:

template<class T> 
constexpr typename std::add_const<T>::type& as_const(T& t) noexcept { return t; }

// prevent accidentally creating an lvalue out of a const rvalue
template<class T> void as_const(const T&&) = delete; 

当然,你所做的任何事情都无法防止有人故意抛弃常量。墨菲、马基雅维利等

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止意外地在非常量对象上调用变异函数? 的相关文章

  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • 是否可以强制 XMLWriter 将元素写入单引号中?

    这是我的代码 var ptFirstName tboxFirstName Text writer WriteAttributeString first ptFirstName 请注意 即使我使用 ptFirstName 也会以双引号结束 p
  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • 将布尔参数传递给 SQL Server 存储过程

    我早些时候问过这个问题 我以为我找到了问题所在 但我没有 我在将布尔参数传递给存储过程时遇到问题 这是我的 C 代码 public bool upload false protected void showDate object sende
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • 从文件中读取 GLSL 着色器

    我正在尝试从如下所示的文件中读取顶点和片段着色器 version 330 core in vec3 ourColor out vec4 color void main color vec4 ourColor 1 0f but when i
  • 如何将 ASCII 字符的十六进制值写入文本文件?

    这是我目前所拥有的 void WriteHexToFile std ofstream stream void ptr int buflen char prefix unsigned char buf unsigned char ptr fo
  • 执行错误日志记录的简单方法?

    我创建了一个小型 C winforms 应用程序 作为一项附加功能 我正在考虑向其中添加某种形式的错误日志记录 有人对解决这个问题有什么好的建议吗 这是我从未考虑过添加到以前的项目中的功能 因此我愿意接受有更多经验的开发人员的建议 我正在考
  • HTML 将 Phaser 移动到容器 div 中

    目前正在 Phaser 中制作一个基于浏览器的游戏并尝试将其添加到容器中div我创建的标签 但是移相器似乎将自身推到容器下方div 两张截图对比 http gyazo com 3cc9b9333cf89d7fc879bd2cdc741609
  • 如何在 Strapi 中将用户不可编辑的字段添加到内容类型?

    说我有一个post具有以下 4 个字段的内容类型 title 细绳 content 细绳 slug 细绳 author 关系 如何添加第五个字段 该字段的值取决于上述 4 个字段之一且用户不可编辑 说吧 我想要一个wordCount字段中的
  • CFBundle可执行错误

    无法安装应用程序 Users myname Documents SDK iPhoneApplications x build Debug iphoneos x app 处的应用程序未指定 CFBundleExecutable 我不知道这意味
  • 在 Silverlight 4 中编辑标题

    我们正在开发一个浏览器外的 Silverlight 4 应用程序 并希望在应用程序加载后更改标题 Example public partial class MainPage UserControl public MainPage Initi
  • 递归深度有限的旅行目录树

    我需要递归地处理目录树中的所有文件 但深度有限 这意味着例如在当前目录和前两个子目录级别中查找文件 但不再进一步查找 在这种情况下 我必须处理例如 subdir1 subdir2 file 但不是 subdir1 subdir2 subdi
  • Xunit 中的测试异常 ()

    我正在尝试对此方法编写 Xunit 测试 public async Task
  • 在 DLL 中,函数表的结构如何?

    我一直在研究不明确支持我的操作系统的设备库的实现 特别是 我有一个反汇编的 DLL 以及大量的支持源代码 现在 功能表 导出表是如何构造的 我的理解是 第一个结构 data部分是 RVA 表 接下来是通过索引链接到第一个地址表的字符串表 这
  • Linux 内核线程没有地址空间

    为什么Linux内核线程没有地址空间 对于任何要执行的任务 它都应该有一个内存区域 对吗 内核线程的文本和数据去了哪里 内核线程确实有一个地址空间 只是他们都有同一个 这并不妨碍它们各自拥有不同的堆栈 文本和数据放置在内核地址空间 由所有线
  • 当数据包含 UTF 8 字符时 PHP 导出 CSV

    在 MySQL 中 我将数据字段类型设置为utf8 bin我正在以 Unicode 存储数据 文本在网页中正确显示 我想生成 Excel 文件 将数据从我的表导出到其中 输出在 xls and cvs是 我在这里查看了其他答案 它被提到使用
  • 如何在Android中编写特殊字符

    我想将单位添加到我的TextView 例如幂 2 如文本行上方的小写字母 微符号 等 我怎样才能做到这一点 是的 您可以使用 Unicode 字符Textview TextView tvtext new TextView this tvTe
  • 下载NLTK数据时出现PermissionError

    我使用 Anaconda 的 Python 3 6 3 发行版 它安装了 NLTK 但没有安装我项目所需的 NLTK DATA 问题是 当我尝试安装时 nltk download I get PermissionError Errno 13
  • 如何拆分同时包含分隔符和转义分隔符的字符串?

    我的字符串分隔符是 分隔符在字符串中转义为 E g irb main 018 0 gt s a b d e gt a b d e irb main 019 0 gt s split gt a b d e 有人可以建议我正则表达式 这样 sp
  • jQuery $.live() 不适用于 iPhone 上的表格行

    我正在使用 jQuery 使表格行可点击 live 功能 可以在 Chrome Firefox 甚至桌面 Windows Safari 上完美运行 但不能在 iPhone 上运行 bind 到处都可以使用 但出于明显的原因 我想使用其他功能
  • 代码优先更改数据源,无需连接字符串

    我在创建 MVC4 应用程序时似乎遇到问题 我采用了代码优先方法来创建模型 但 web config 文件中似乎没有创建连接字符串 构建的数据库似乎是在 localhost SQLEXPRESS 实例上构建的 但我想将其更改为外部数据源 如
  • svg 中的简单填充图案:对角线阴影

    我如何填充 SVG 形状 不是使用单一颜色 图像或渐变 而是使用阴影图案 如果可能的话对角线 已经两个小时了 我什么也没发现 至少在2005年之后 我认为一个可能的破解方法是使用孵化的 PNG 作为填充 但这并不理想 我在互联网上也没有找到
  • 使用 Pandas/ExcelWriter 对单元格中的文本部分进行着色

    如何使用 pandas 数据框和 ExcelWriter 对写入 Excel 文件的部分文本进行着色 我已经设置了使用背景颜色和文本颜色以及不同内容来格式化单元格 但是您可以将格式设置仅应用于字符串 1 3 5 的单元格中的第一个逗号分隔值
  • 如何防止意外地在非常量对象上调用变异函数?

    假设我们有一个 myType 类型的对象 obj 并且我们希望将其传递给函数 Foo 该函数返回一些有关 obj 的有价值的信息 函数 Bar 是声明 obj 的地方 也是从中调用 Foo 的地方 如下所示 void Bar myType