我阅读了B. Stroustrup的Thoughts about C++17中的契约(Contract),并参加了一个简短的介绍契约(Contract)的演讲,但我不确定我是否真的了解它们。
因此,我进行了一些询问,如果可以用一些示例进行说明:

  • 契约(Contract)是否可以更好地替代经典assert(),并且应该一起使用吗?简而言之,对于软件开发人员而言,真正签订了哪些契约(Contract)?
  • 契约(Contract)会影响我们处理异常(exception)的方式吗?如果是,我们应该如何使用异常(exception)和契约(Contract)?
  • 使用契约(Contract)会在执行时带来开销吗?是否可以在发布代码上停用它们?

  • proposal N4415:

    感谢@Keith Thompson评论:

    最佳答案

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

    契约(Contract)以assert多年来一直尝试的原始方式完成工作。它们既是文档,又是运行时断言,用于说明应如何期望调用方调用函数以及在函数返回后调用方可以期望代码处于哪种状态。这些通常称为前置条件和后置条件或不变式。

    这有助于清理实现方面的代码,因为使用契约(Contract),我们可以假定一旦执行进入函数内部,您的参数将处于有效状态(即您期望的状态)。

    后置条件部分可能会更改您处理异常的方式,因为使用契约(Contract)时,您必须确保引发异常不会破坏后置条件。这通常意味着您的代码必须是异常安全的,尽管这意味着强异常保证还是基本保证取决于您的条件。

    例:

    类数据;
    类MyVector {
    上市:
    void MyVector::push_back(Elem e)[[确保:数据!= nullptr]]
    {
    if(大小> =容量)
    {
    数据* p =数据;
    数据= nullptr;//只是为了示例...
    数据=新数据[容量* 2];//可能引发异常
    //将p复制到数据中并删除p
    }
    //将元素添加到末尾
    }
    私有(private)的:
    数据*数据;
    //其他数据
    };

    在此处的此示例中,如果newData的构造函数引发异常,则将违反您的后置条件。这意味着您应该更改所有此类代码,以确保从未违反您的契约(Contract)!

    当然,就像assert一样,契约(Contract)可能包含运行时开销。但是区别在于,由于可以将协定作为函数声明的一部分放置,因此编译器可以进行更好的优化,例如在调用方的位置评估条件,甚至在编译时对其进行评估。这篇文章开头提到的文档的第1.5节讨论了根据您的构建配置关闭契约(Contract)的可能性,就像普通的旧断言一样。

    关于c++ - 什么是契约(Contract)(针对C++ 17提出的契约(Contract))?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31317155/

    10-13 01:58