什么是合约(如 C++17 的建议)?

2024-05-02

我读到了有关合同的内容关于 C++17 的思考 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4492.pdf由 B. Stroustrup 撰写,并协助进行了一次小型演讲,讨论了它们,但我不确定我是否真正理解了它们。

所以我有一些疑问,是否可以用一些例子来说明它们:

  • 合同只是经典合同的更好替代品吗?assert(),它们应该一起使用吗?对于软件开发人员来说,哪些合同实际上是简单的?

  • 合同会影响我们处理异常的方式吗?如果是,我们应该如何使用例外和合同?

  • 使用合约是否意味着执行时的开销?我们可以在发布代码上停用它们吗?

来自提案 N4415 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf:

Vector 类的索引运算符的前置条件契约可以编写为:
T& operator[](size_t i) [[expects: i < size()]];

类似地,ArrayView 类的构造函数上的后置条件契约可以表示为:ArrayView(const vector<T>& v) [[ensures: data() == v.data()]];

感谢@Keith Thompson 评论:

合约没有进入 C++20. 一个新的研究小组 SG21 已经成立。 https://herbsutter.com/2019/07/20/trip-report-summer-iso-c-standards-meeting-cologne/


据我从这份文件中读到:http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf

合同做什么assert多年来一直尝试以原始方式进行。它们既是文档,也是运行时断言,说明调用者应该如何调用该函数,以及调用者期望函数返回后代码处于什么状态。这些通常称为前置条件和后置条件,或不变量。

这有助于清理实现方面的代码,因为通过合约,我们可以假设一旦执行进入您的函数,您的参数就处于有效状态(您期望它们是什么)。

后置条件部分可能会改变您处理异常的方式,因为对于合约,您必须确保抛出异常不会破坏您的后置条件。这通常意味着您的代码必须是异常安全的,尽管这意味着强异常保证还是基本保证取决于您的条件。

Example:

class Data;
class MyVector {
public:
    void MyVector::push_back(Elem e) [[ensures: data != nullptr]]
    {
        if(size >= capacity)
        {
            Data* p = data;
            data = nullptr; // Just for the sake of the example...
            data = new Data[capacity*2]; // Might throw an exception
            // Copy p into data and delete p
        }
        // Add the element to the end
    }
private:
     Data* data;
     // other data
};

在这个例子中,如果new or Data的构造函数抛出异常,您的后置条件被违反。这意味着您应该更改所有此类代码,以确保您的合同永远不会被违反!

当然,就像assert,合同可能包括运行时开销。但不同之处在于,由于契约可以作为函数声明的一部分,因此编译器可以进行更好的优化,例如评估调用者站点的条件,甚至在编译时评估它们。本文开头提到的文档的第 1.5 节讨论了根据您的构建配置关闭合约的可能性,就像普通的旧断言一样。

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

什么是合约(如 C++17 的建议)? 的相关文章

  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46

随机推荐