我可以控制静态对象被破坏的顺序吗?有没有办法强制执行我想要的订单?例如,以某种方式指定我想要最后销毁某个对象,或者至少在另一个静态对象之后销毁?
我听说Qt中的对象会自动删除他们的孩子,我想知道在这些情况下会发生什么.
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
/*
QLabel label("label"); // Program will crash. Destruct order is 1. widget, 2. layout, 3. label
QHBoxLayout layout; // But layout will be deleted twice
QWidget widget;
*/
QWidget widget; // Program doesn't seem to crash but is it safe ? Does Qt use
QHBoxLayout layout; // delete to operate on already destructed children ?
QLabel label("label");
layout.addWidget(&label); // layout is label's …Run Code Online (Sandbox Code Playgroud) 考虑具有以下签名的函数:
(defn make-widget [& {:keys [x y] :or {x 10 y 20}}]
...)
Run Code Online (Sandbox Code Playgroud)
将地图传递给函数的最佳方法是什么,例如:
(make-widget {:x 100})
Run Code Online (Sandbox Code Playgroud)
要么
(make-widget {:y 200 :x 0})
Run Code Online (Sandbox Code Playgroud)
目前有什么我想到的是通过vec,flatten并apply如:
(apply make-widget (flatten (vec ({:x 100}))
Run Code Online (Sandbox Code Playgroud)
我坚信有更好的方法可以做到这一点.你能考虑一下吗?
根据n4640中的5.2.2/4"函数调用"(n4659中的8.2.2/4),在调用者的上下文中创建和销毁函数参数.并且允许实现将函数参数的破坏延迟到封闭的完整表达式的末尾(作为实现定义的特征).请注意,选择不是未指定的,而是实现定义的.
(目前还不完全清楚这与3.3.3"块范围"(n4659中的6.3.3)是否一致,这似乎意味着函数参数具有块范围,然后是3.7.3"自动存储持续时间"(6.7.3)在n4659)中,它表示块作用域变量的存储一直存在,直到它们被创建的块出现.但是我们假设我在措辞中缺少/误解了一些内容.显然现在函数参数将有自己的范围)
据我所知,ABI要求GCC和Clang将函数参数的销毁延迟到完全表达式的末尾,即这是这些编译器的实现定义行为.我猜想在类似的实现中,只要在调用表达式中使用这些引用/指针,就可以返回对函数参数的引用/指针.
但是,以下示例在GCC中的段错误并且在Clang中正常工作
#include <iostream>
#include <string>
std::string &foo(std::string s)
{
return s;
}
int main()
{
std::cout << foo("Hello World!") << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
两个编译器都发出关于返回对局部变量的引用的警告,这在这里是完全合适的.快速检查生成的代码表明,两个编译器确实将参数的破坏延迟到表达式的末尾.但是,GCC仍故意返回"null引用" foo,导致崩溃.与此同时,Clang表现为"按预期",返回对其参数的引用,该参数的s存活时间足以产生预期的输出.
(简单来说,GCC在这种情况下很容易愚弄
std::string &foo(std::string s)
{
std::string *p = &s;
return *p;
}
Run Code Online (Sandbox Code Playgroud)
它修复了GCC下的段错误.)
在这种情况下GCC的行为是否合理,假设它保证参数的"晚期"破坏?我是否遗漏了标准中的其他段落,即返回对函数参数的引用始终未定义,即使它们的生命周期是由实现扩展的?
我知道向量元素破坏顺序不是由C++标准定义的(参见std :: vector元素的破坏顺序),我看到我检查过的所有编译器从头到尾都做了这个破坏 - 这对我来说非常令人惊讶动态和静态数组以相反的顺序执行,而这种相反的顺序在C++世界中经常出现.
要严格:我知道"容器成员......可以使用例如插入和擦除成员函数以任何顺序构造和销毁",并且我不投票支持"容器以保留某些记录这些更改".我只想投票将当前的矢量析构函数实现从前向破坏改为向后破坏元素 - 仅此而已.并且可能将此规则添加到C++标准中.
而原因呢?从数组到向量的变化会更加安全.
真实世界示例:我们都知道互斥锁定和解锁顺序非常重要.并确保解锁发生 - 使用ScopeGuard模式.然后销毁订单很重要.考虑这个例子.那里 - 从数组切换到向量会导致死锁 - 只是因为它们的破坏顺序不同:
class mutex {
public:
void lock() { cout << (void*)this << "->lock()\n"; }
void unlock() { cout << (void*)this << "->unlock()\n"; }
};
class lock {
lock(const mutex&);
public:
lock(mutex& m) : m_(&m) { m_->lock(); }
lock(lock&& o) { m_ = o.m_; o.m_ = 0; }
lock& operator = (lock&& o) {
if (&o != this) {
m_ = o.m_; o.m_ = 0; …Run Code Online (Sandbox Code Playgroud) A(3)在"Here"打印之前,不应该暂时销毁吗?
#include <iostream>
struct A
{
int a;
A() { std::cout << "A()" << std::endl; }
A(int a) : a(a) { std::cout << "A(" << a << ")" << std::endl; }
~A() { std::cout << "~A() " << a << '\n'; }
};
int main()
{
A a[2] = { A(1), A(2) }, A(3);
std::cout << "Here" << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
A(1)
A(2)
A(3)
Here
~A() 3
~A() 2
~A() 1
Run Code Online (Sandbox Code Playgroud)
我正在看这篇文章,它说"在进入基类析构函数后,该对象成为基类对象,而C++的所有部分 - 虚函数,dynamic_casts等 - 以这种方式对待它." 这是否意味着vptr在破坏期间发生了变化?这是怎么发生的?
问题:我如何告诉 Spring 一组具有自定义范围的 bean 都应该被视为垃圾,以便同一线程上的下一个请求不会重用它们的状态?
我所做的:我在 Spring 中实现了一个自定义范围,以模拟请求范围(HttpRequest)的生命周期,但对于 TcpRequests。它与此处找到的内容非常相似。
我发现的许多自定义范围的例子是原型或单例的变体,没有显式终止 bean,或者,它们基于本地线程或 ThreadScope,但它们没有描述告诉 Spring 生命周期已经结束并且所有豆类应该销毁。
我尝试过的事情(可能不正确):
事件 + 侦听器指示作用域的开始和结束(这些发生在收到消息时和发送响应之前);在侦听器中,范围被明确清除,从而清除线程本地实现(scope.clear())使用的整个映射。在测试中手动处理时,清除范围确实会导致对 context.getBean() 的下一次调用返回一个新实例,但是我在单例类中自动装配的 bean 没有得到一个新 bean——它一遍又一遍地使用相同的 bean .
实现:BeanFactoryPostProcessor、BeanPostProcessor、BeanFactoryAware、DisposableBean 并尝试在所有 Disposable bean 实例上调用 destroy() 的侦听器;类似这样的东西,但仅适用于我的自定义范围。这似乎失败了,因为没有明确结束 bean 的生命周期,尽管我在收到范围结束事件时调用 customScope.clear() ;结束范围似乎并不转化为“结束与此范围关联的所有 bean”。
我已经广泛阅读了 Spring 文档,似乎很明显 Spring 不管理这些自定义 bean 的生命周期,因为它不知道何时或如何销毁它们,这意味着必须告诉它何时以及如何销毁摧毁他们;我试图阅读和理解 Spring 提供的 Session 和 Request 范围,以便我可以模仿这一点,但我遗漏了一些东西(同样,这些对我来说不可用,因为这不是一个网络感知应用程序,我不是使用 HttpRequests,这是我们应用程序结构的重大变化)
有没有人能够指出我正确的方向?
我有以下代码示例:
Xml 上下文配置:
<int-ip:tcp-connection-factory id="serverConnectionFactory" type="server" port="19000"
serializer="javaSerializer" deserializer="javaDeserializer"/>
<int-ip:tcp-inbound-gateway id="inGateway" connection-factory="serverConnectionFactory"
request-channel="incomingServerChannel" error-channel="errorChannel"/>
<int:channel id="incomingServerChannel" />
<int:chain input-channel="incomingServerChannel">
<int:service-activator ref="transactionController"/> …Run Code Online (Sandbox Code Playgroud) 目前在我的程序中,我有一个Startup表单和一个Main表单.启动表单显示一两秒钟.
现在,我在计时器中有以下代码:
frmStartup.Destroy;
frmMain := TfrmMain.Create(Self);
frmMain.Show;
Run Code Online (Sandbox Code Playgroud)
现在,我不确定这是否是正确的方法.它可行,但在调用时application.Terminate();
我收到一条访问违规消息,导致我相信我在破坏启动表单时做错了什么. .
如果有人能够显示正确的程序来做我想要的(非模态),我将不胜感激.
提前致谢,
编辑:
感谢所有反馈,我通过简单地添加代码修复了访问冲突:
Action := caFree;
Run Code Online (Sandbox Code Playgroud)
进入frmStartup.formClose方法.
__del__假设有人不知道和之间有什么区别__delete__?写一个解释。
destruction ×10
c++ ×6
clojure ×1
construction ×1
creation ×1
custom-scope ×1
delphi ×1
destructor ×1
forms ×1
java ×1
lifetime ×1
map ×1
procedure ×1
python ×1
python-3.x ×1
qt ×1
scope ×1
spring ×1
spring-boot ×1
standards ×1
static ×1
temporary ×1
vector ×1
vptr ×1