C++CoreGuidelines:Understanding`noexcept`Specifica

理解noexcept说明符的核心价值

noexcept说明符是C++11标准引入的关键特性,用于指定一个函数是否可能抛出异常。它不仅是一种文档化手段,更是一种承诺,编译器可以利用这个承诺进行积极的优化。从C++ Core Guidelines的角度来看,正确使用noexcept对于编写健壮、高效且易于维护的现代C++代码至关重要。函数被标记为noexcept意味着它向调用者保证,在正常执行路径上不会抛出任何异常。这种确定性允许编译器省略不必要的异常处理代码,从而可能生成更小、更快的可执行文件。

noexcept的基本语法与用法

noexcept有两种主要形式。第一种是简单的无条件的noexcept,直接在函数声明后使用`noexcept`关键字。例如:`void my_function() noexcept;`。这声明了`my_function`保证不会抛出异常。第二种是条件性的noexcept,形式为`noexcept(expression)`,其中的表达式在编译时求值,结果为true或false,以此决定函数是否被视为noexcept。例如:`void swap_my_type(MyType& other) noexcept(noexcept(other.swap(other)));`。这种形式常用于模板代码,根据模板参数的类型特性来动态决定函数的异常规格。

无条件noexcept

这是最直接的形式,适用于开发者明确知道函数实现绝不会抛出异常的情况。例如,一个只进行简单算术运算或操作栈上对象的函数。一旦声明为`noexcept`,如果函数内部意外抛出了异常,程序会立即调用`std::terminate`终止,而不是展开栈寻找异常处理器。因此,这种承诺必须是谨慎且可靠的。

条件noexcept

条件noexcept极大地增强了泛型编程的灵活性和安全性。它通常与`std::is_nothrow_constructible`、`std::is_nothrow_move_constructible`等类型特征 trait 结合使用。在编写像`std::vector`这样的容器时,移动构造函数可以标记为`noexcept(noexcept(T(std::declval())))`。这意味着,只有当类型T的移动构造函数本身是noexcept时,容器的移动构造函数才是noexcept。这允许标准库在需要提供强异常安全保证时(如`vector`的重新分配),优先使用高效且不会失败的移动操作,而不是可能失败的拷贝操作。

C++ Core Guidelines的关键建议

C++ Core Guidelines就noexcept的使用提供了一系列具体建议,其核心思想是“谨慎而明确”。

F.6: 如果您的函数可能不抛出异常,请将其声明为noexcept

这是一条基本原则。将不会抛出异常的函数标记为noexcept是一种低成本的优化手段,既为编译器提供了优化机会,也为代码使用者提供了明确的接口契约。它告诉调用者可以安全地在不允许异常抛出的上下文中(如析构函数)使用该函数。

C.85: 使移动操作noexcept

这是关于noexcept最重要和最著名的准则之一。标准库中的许多组件,特别是容器,在需要重新分配资源时(例如`std::vector::push_back`),会检查元素类型的移动构造函数和移动赋值运算符是否为noexcept。如果是,容器会优先使用移动操作以保证效率(因为移动通常比拷贝快)和强异常安全(因为移动操作不会失败)。如果移动操作不是noexcept,容器为了安全起见,可能会回退到拷贝操作,从而导致性能损失。因此,为你自定义类型的移动操作实现noexcept通常是一个好习惯。

C.80: 如果使用默认的移动操作,请确保其正确且为noexcept

当你使用`= default`来让编译器生成移动操作时,编译器通常会根据数据成员的移动操作来生成。如果所有基类和成员的移动操作都是noexcept,那么默认生成的移动操作也是noexcept。遵循此准则可以确保你的类型能够与标准库协同工作,获得最佳性能。

E.12: 绝对不要在析构函数、内存释放函数和swap函数中抛出异常,并将它们声明为noexcept

析构函数在栈展开过程中被调用,如果此时再抛出异常,程序将立即终止。因此,析构函数必须设计为不抛出异常,并且明确标记为`noexcept`。同样,`operator delete`和`swap`函数也通常被期望是异常安全的,标记为noexcept可以强化这一预期,并允许它们在关键路径上被安全使用。

noexcept的误用与风险

尽管noexcept益处良多,但误用它会带来严重风险。最核心的风险在于,将一个实际上可能抛出异常的函数错误地标记为noexcept。当这样的函数真的抛出异常时,程序会立即调用`std::terminate()`,导致不可控的崩溃,而不是按照正常的异常处理流程进行栈展开和资源清理。这会使得调试变得异常困难,并可能导致资源泄漏。因此,只有在百分之百确定函数不会抛出异常,或者函数内部的任何异常都在函数内部被捕获并处理的情况下,才应使用noexcept。

noexcept操作符

`noexcept`同时也是一个操作符(不同于说明符),用于在编译时检查一个表达式是否声明为不抛出异常。其形式为`noexcept(expression)`,返回一个bool类型的编译时常量。这个操作符在编写条件noexcept说明符和模板元编程时极其有用,如前文提到的swap示例。它允许我们根据表达式的异常规格来推导和定义我们自己的函数的异常规格。

总结

总而言之,`noexcept`是现代C++异常规格机制的核心。遵循C++ Core Guidelines来使用noexcept,能够显著提升代码的性能、可预测性和互操作性。关键在于将其视为一个严肃的承诺:只在确有把握时使用,尤其要确保移动操作、析构函数和swap函数正确标记。通过审慎地应用noexcept,开发者可以编写出更清晰、更健壮且更高效的C++程序。

握手和证书验证在httpd模块请求入口那里就已经实现了对https的处理,这里是不是可以不用修改?基本上只要考虑事件推送pull point和basic notify相关,基于我前面给你的onvif协议上对此的规范,能不能重新给出完整的修改,分步骤,对每一步修改繇指出是根据协议规范上的哪一点来修改的?原因是什么?怎么修改?请根据协议重新对soap_tev.c和soap_event.c的代码进行修改——Real-time Pull-Point Notification Interface This section introduces the Real-time Pull-Point Notification Interface. This interface provides a firewall friendly notification interface that enables real-time polling and initiates all client communications. This interface is used in the following way: The client asks the device for a pull point with the CreatePullPointSubscriptionRequest message. The device evaluates the subscription request and returns either a CreatePullPointSubscriptionResponse or one of the Fault codes. If the subscription is accepted, the response contains a WS-EndpointReference to the instantiated pull point. This WS-Endpoint provides a PullMessages operation, which is used by the client to retrieve Notifications. Additionally it provides the Renew and Unsubscribe operations of the Base Subscription Manager Interface. The sequence diagram of the interaction is shown in Figure 6. Client Event Service CreatePullPoint SubscriptionRequest Instantiate CreatePullPoint SubscriptionResponse PullMessages Request PullPoint PullMessages Response Unsubscribe Request Unsubscribe Response Figure 6: Sequence diagram for the Real-time Pull-Point Notification Interface The device immediately responds with notifications that have been aggregated on behalf of the client. If there are no aggregated notifications, the device waits to respond until either a notification is produced for the client or the specified Timeout has exceeded. In any case, the response will contain, at most, the number of notifications specified by the MessageLimit parameter. The client can poll the notifications in real-time when it starts a new PullMessagesRequest immediately after each PullMessagesResponse. For a device implementation it is important to support multiple pull points (including multiple pullpoints per client) in order to allow precise event generation. If a device would only support one subscription at a time a client would need to subscribe without any scope restriction, because changing of event subscription is not possible. Hence this would require the device to serve all available events for which the device would have to activate all subsystems that generate events. This may cause unnecessary load by e.g. activating multiple motion detectors and similar without need. Additionally the traffic produced by all these events may cause a substantial network load. ONVIF™– 86 ONVIF Core Spec – Ver. 24.12 If the device supports persistent notification storage, see 9.1.7, the WS-Endpoint also provides a Seek opera tion. This operation allows to reposition the pull pointer into the past. With the Seek operation it is also possible to reverse the pull direction. There is also a BeginOfBuffer event, as defined in 9.11.1, that signals the start of the buffer. An ONVIF compliant device shall implement the Real Time Pull-Point Notification Interface. 9.1.1 Create pull point subscription An ONVIF compliant device shall provide the CreatePullPointSubscription command. If no Filter element is specified the pullpoint shall notify all occurring events to the client. By default the pull point keep alive is controlled via the PullMessages operation. In this case, after a PullMes sages response is returned, the subscription should be active for at least the timeout specified in the PullMes sages request. A device shall support an absolute time value specified in utc as well as a relative time value for the InitialTer minationTime parameter. A device shall respond both parameters CurrentTime and TerminationTime as utc using the ‘Z’ indicator. The following optional subscription policy elements are defined in tev:SubscriptionPolicy: • tev:ChangedOnly A pullpoint should not provide Initialized nor Deleted events for Properties. Both request and response message contain the same elements as the SubscriptionRequest and Response of [WS-BaseNotification] without the ConsumerReference. REQUEST: • Filter - optional [wsnt:FilterType] Optional filtering for e.g. topics. • InitialTerminationTime - optional [wsnt:AbsoluteOrRelativeTimeType] Initial termination time. • SubscriptionPolicy - optional [xs:any] RESPONSE: • SubscriptionReference [wsa:EndpointReferenceType] Endpoint reference of the subscription to be used for pulling the messages. • CurrentTime [xs:dateTime] Current time of the server for synchronization purposes. • TerminationTime [xs:dateTime] Date time when the PullPoint will be shut down without further pull requests. FAULTS: • The same faults as for Subscription Request of the [WS-BaseNotification] are used. ACCESS CLASS: READ_MEDIA 9.1.2 Pull messages The device shall provide the following PullMessages command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. ONVIF™– 87 ONVIF Core Spec – Ver. 24.12 The device shall support a Timeout of at least one minute. The device shall not respond with a PullMessages FaultResponse when the MessageLimit is greater than the device supports. Instead, the device shall return up to the supported messages in the response. The response behavior shall be one of three types: • If there are one or more messages waiting (i.e., aggregated) when the request arrives, the device shall immediately respond with the waiting messages, up to the MessageLimit. The device shall not discard unsent messages, but shall await the next PullMessages request to send remaining messages. • If there are no messages waiting, and the device generates a message (or multiple simultaneous messages) prior to reaching the Timeout, the device shall immediately respond with the generated messages, up to the MessageLimit. The device shall not wait for additional messages before returning the response. • If there are no messages waiting, and the device does not generate any message prior to reaching the Timeout, the device shall respond with zero messages. The device shall not return a response with zero messages prior to reaching the Timeout. A device shall respond both parameters CurrentTime and TerminationTime as utc using the ‘Z’ indicator. After a seek operation the device shall return the messages in strict message utc time order. Note that this requirement is not applicable to standard realtime message delivery where the delivery order may be affected by device internal computations. A device should return an error (UnableToGetMessagesFault) when receiving a PullMessages request for a subscription where a blocking PullMessage request already exists. REQUEST: • Timeout [xs:duration] Maximum time to block until this method returns. • MessageLimit [xs:int] Upper limit for the number of messages to return at once. A server implementation may decide to return less messages. RESPONSE: • CurrentTime [xs:dateTime] The date and time when the messages have been delivered by the web server to the client. • TerminationTime [xs:dateTime] Date time when the PullPoint will be shut down without further pull requests. • NotificationMessage - optional, unbounded [wsnt:NotificationMessageHolderType] List of messages. This list shall be empty in case of a timeout. PULLMESSAGESFAULTRESPONSE: • MaxTimeout [xs:duration] Only when the Timeout exceeds the upper limit supported by the device. Not sent when the Message Limit is exceeded. The Fault Message shall contain the upper limits for both parameters. • MaxMessageLimit [xs:int] FAULTS: • No specific fault codes. ACCESS CLASS: READ_MEDIA ONVIF™– 88 ONVIF Core Spec – Ver. 24.12 9.1.3 Renew An ONVIF compliant device shall support this command if it signals support for [WS-Base Notification] via the MaxNotificationProducers capability. The command shall at least support a Timeout of one minute. A device shall respond both parameters Cur rentTime and TerminationTime as utc using the ‘Z’ indicator. REQUEST: • TerminationTime [wsnt:AbsoluteOrRelativeTimeType] The new relative or absolute termination time. RESPONSE: • CurrentTime [xs:dateTime] The current server time. • TerminationTime [xs:dateTime] The updated TerminationTime for the SubscriptionManager. RESOURCEUNKNOWNFAULTRESPONSE: • Timestamp [xs:dateTime] The pull point reference is invalid • Originator - optional [wsa:EndpointReferenceType] • ErrorCode - optional [xs:any] UNACCEPTABLETERMINATIONTIMEFAULTRESPONSE: • Timestamp [xs:dateTime] The Timeout exceeds the upper limit supported by the device. • Originator - optional [wsa:EndpointReferenceType] • ErrorCode - optional [xs:any] FAULTS: • No specific fault codes. ACCESS CLASS: READ_MEDIA 9.1.4 Unsubscribe The device shall provide the following Unsubscribe command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. The command is defined in section 6.1.2 of [OASIS Web Ser vices Base Notification 1.3 [http://docs.oasis-open.org/wsn/wsn-ws_base_notification-1.3-spec-os.pdf]]. This command shall terminate the lifetime of a pull point. REQUEST: This is an empty message. RESPONSE: This is an empty message. ONVIF™– 89 ONVIF Core Spec – Ver. 24.12 RESOURCEUNKNOWNFAULTRESPONSE: • Timestamp [xs:dateTime] The pull point reference is invalid • Originator - optional [wsa:EndpointReferenceType] • ErrorCode - optional [xs:any] FAULTS: • No specific fault codes. ACCESS CLASS: READ_MEDIA 9.1.5 Seek A device supporting persistent notification storage as defined in section 9.1.7 shall provide the following Seek command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. On a Seek a pullpoint shall abort any event delivery including any initial states of properties. Furthermore the pullpoint should flush events not already queued for transmission from the transmit queue. After a Seek request a pullpoint shall ignore the behavior described in section 9.6 for properties. A device shall only set the subscription in reverse pull mode if the Reverse argument is present and set to “true”. The UtcTime argument of the Seek request shall be matched against the UtcTime attribute of the notifications in the persistent notification storage. When Seek is used in the forward mode a device shall position the pull pointer to include all NotificationMes sages in the persistent storage with a UtcTime attribute greater than or equal to the Seek argument. When Seek is used in reverse mode a device shall position the pull pointer to include all NotificationMessages in the in the persistent storage with a UtcTime attribute less than or equal to the Seek argument. A device shall not provide information of the initial generate property state as response to a call to the Seek method. REQUEST: • UtcTime [xs:datetime] This message shall be addressed to a PullPoint in order to readjust the pull position: • Reverse - optional [xs:bool] RESPONSE: This is an empty message. FAULTS: • No specific fault codes. ACCESS CLASS: READ_MEDIA 9.1.6 Pull Point Lifecycle Figure 6 depicts the basic operation of a pull point. This chapter states the requirements on the pull point lifecycle. ONVIF™– 90 ONVIF Core Spec – Ver. 24.12 A device shall create a new pull point on each CreatePullPointSubscription command as long as the number of instantiated pull points does not exceed the capability MaxPullPoints. Each pull point shall have a unique endpoint reference to which the client can direct its consecutive operations on the pull point. A pull point shall exist until either its termination time has elapsed or the client has requested its disposal via an Unsubscribe request. There are no requirements regarding persistency of a pull point across a power cycle of a device. 9.1.7 Persistent notification storage To ensure that no notifications are lost by a client a device may store its notifications. The stored notifications can at any time be retrieved by a client. The device shall indicate if its support persistent notification storage with the PersistentNotificationStorage capability. See section 9.8. This specification defines that the interface to the persistent storage allows linear access via the originating message event time. This holds also for events that are delivered out of order in the live streaming case due to e.g. computational delay. The details of what notification and how and where those notifications actually are stored are outside the scope of this specification. Removal policy of stored notifications to get room for new ones is also out of scope. 9.2 Notification Streaming Interface This section defines the transmission of events via RTP streaming packets. For details regarding the configu ration see section “Metadata Configuration“ of the ONVIF Media Service Specification. The following requirements apply if a devices supports transmission of events via RTP streaming packets: • The events shall be encoded as wsnt:NotificationMessage as defined in [WS-BaseNotification] to trans port the Message Payload, the Topic and the ProducerReference. • Multiple instances of the wsnt:NotificationMessage elements can be placed within a metadata docu ment. • Since there is no explicit SubscriptionReference with streaming notifications, the wsnt:NotificationMes sage shall not contain the SubscriptionReference element. 9.3 Basic Notification Interface Section 9.3.1 briefly introduces the Basic Notification Interface of the [WS-BaseNotification] specification. Sec tion 9.3.2 summarizes the mandatory and the optional interfaces of the [WS-BaseNotification] specification. Please refer for a full documentation of the Basic Notification Interface to the [WS-BaseNotification] specifica tion. 9.3.1 Introduction The following logical entities participate in the notification pattern: Client: implements the NotificationConsumer interface. Event Service: implements the NotificationProducer interface. Subscription Manager: implements the BaseSubscriptionManager interface. The Event Service and the Subscription Manager should be instantiated on a device. Typical messages exchanged between the entities are shown in the sequence diagram in Figure 7. First, the client establishes a connection to the Event Service. The client can then subscribe for certain notifications by sending a SubscriptionRequest. If the Event Service accepts the Subscription, it dynamically instantiates a SubscriptionManager representing the Subscription. The Event Service shall return the WS-Endpoint-Address of the SubscriptionManager in the SubscriptionResponse. ONVIF™– 91 ONVIF Core Spec – Ver. 24.12 In order to transmit notifications matching the Subscription, another connection is established from the Event Service to the client. Via this connection, the Event Service sends a one-way Notify message to the Notifica tionConsumer interface of the client. Corresponding notifications can be sent at any time by the Event Service to the client, while the Subscription is active. To control the Subscription, the client directly addresses the SubscriptionManager returned in the Subscrip tionResponse. In the SubscriptionRequest the client can specify a termination time. The SubscriptionManager is automatically destroyed when the termination time is reached. RenewRequests can be initiated by the client in order to postpone the termination time. The client can also explicitly terminate the SubscriptionManager by sending an UnsubscribeRequest. After a successful Unsubscription, the SubscriptionManager no longer exists. The interaction between EventService and SubscriptionManager is not further specified by the [WS-BaseNo tification] and is up to the implementation of the device. Client Event Service SubscriptionRequest Instantiate SubscriptionResponse Notify RenewRequest RenewResponse Subscription Manager Notify UnsubscribeRequest UnsubscribeResponse Figure 7: Sequence diagram for the Base Notification Interface 9.3.2 Requirements This section details those interfaces of the [WS-BaseNotification] that a device shall provide. An ONVIF compliant device shall support the NotificationProducer Interface of the [WS-BaseNotification] if the capability MaxNotificationProducers is non-zero. The device shall support TopicExpression filters with the dialects described in 9.6.3. The support for MessageContent filters is signalled via the GetEventProperties method. If the device does not accept the InitialTerminationTime of a subscription, it shall provide a valid Ini tialTerminationTime within the Fault Message. The device shall be able to provide notifications using the Noti fy wrapper of the [WS-BaseNotification] specification. The SubscriptionPolicy wsnt:UseRaw is optional for the device. Although the [WS-BaseNotification] has CurrentTime and TerminationTime as optional elements in a SubscribeResponse and RenewResponse, an ONVIF compliant device shall list them in both SubscribeRe sponses and RenewResponse. The device may respond to any GetCurrentMessage request with a Fault mes sage indicating that no current message is available on the requested topic. An ONVIF compliant device shall implement the Base Subscription Manager Interface of the [WS-BaseNotifi cation] specification consisting of the Renew and Unsubscribe operations. The Pausable Subscription Manager Interface is optional. The implementation of Subscriptions as WS-Resources is optional. ONVIF™– 92 ONVIF Core Spec – Ver. 24.12 An ONVIF compliant device shall support time values in request parameters that are given in utc with the ‘Z’ indicator and respond all time values as utc including the ‘Z’ indicator
10-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值