std::包含auto_ptr对象的向量行为奇怪
std::vector of object containing auto_ptr behaves strangely
我想使用 Qt 库为我的应用程序创建一个控制面板,为此我创建了类Controls
类
Controls
:创建一个滑块和旋转以及一个标签,并将它们组织在水平布局中。
但是当我想创建std::vector<Controls>
程序运行没有错误,但现在控件正在创建! 那么为什么没有控件。
控制.h
class Controls
{
private:
QHBoxLayout Layout ;
string Controlname;
std::auto_ptr<QLabel> Label ;
std::auto_ptr<QSlider> Slider ;
std::auto_ptr<QSpinBox> Spin ;
public:
Controls();
Controls(QLayout &Parent , string name , const int &Default_value);
Controls(const Controls ©);
~Controls();
QLabel *const Get_Label()const { return Label.get() ; }
QSlider *const Get_Slider()const { return Slider.get() ; }
QSpinBox *const Get_Spin()const { return Spin.get() ; }
QHBoxLayout *const Get_Layout() {return &Layout;}
void SetValue(const int &newvalue);
Controls &operator= (const Controls ©);
};
控件.cpp
Controls &Controls::operator= (const Controls ©)
{
Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;
this->Controlname = copy.Controlname ;
this->Slider.get()->setValue( copy.Slider.get()->value() );
this->Spin.get()->setValue( copy.Spin.get()->value() );
return *this ;
}
Controls::Controls(const Controls ©)
{
this->Controlname = copy.Controlname ;
this->Slider.get()->setValue( copy.Slider.get()->value() );
this->Spin.get()->setValue( copy.Spin.get()->value() );
}
Controls::Controls()
{
Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;
Slider->setValue(0);
Slider->setOrientation(Qt::Horizontal);
Label->setText(QString ("unamed"));
Spin->setValue(0);
Layout.addWidget(Label.get() , 0 , 0);
Layout.addWidget(Slider.get() , 0 , 0);
Layout.addWidget(Spin.get() , 0 , 0);
QObject::connect(Slider.get() , SIGNAL(valueChanged(int) ) , Spin.get() , SLOT(setValue(int)));
QObject::connect(Spin.get() , SIGNAL(valueChanged(int) ) , Slider.get() , SLOT(setValue(int)));
}
Controls::Controls(QLayout &Parent , string name , const int &Default_value)
{
Controlname = name ;
Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;
Slider->setValue(Default_value*100);
Slider->setOrientation(Qt::Horizontal);
Label->setText(QString (name.c_str()));
Spin->setValue(Default_value*100);
Layout.addWidget(Label.get() , 0 , 0);
Layout.addWidget(Slider.get() , 0 , 0);
Layout.addWidget(Spin.get() , 0 , 0);
QObject::connect(Slider.get() , SIGNAL(valueChanged(int) ) , Spin.get() , SLOT(setValue(int)));
QObject::connect(Spin.get() , SIGNAL(valueChanged(int) ) , Slider.get() , SLOT(setValue(int)));
Parent.addItem(&Layout);
}
void Controls::SetValue(const int &newvalue)
{
Slider.get()->setValue(newvalue);
}
Controls::~Controls()
{
}
主.cpp
int main(int argc, char *argv[])
{
QApplication app (argc , argv );
QVBoxLayout layout ;
auto_ptr<QWidget> Panel = auto_ptr<QWidget> (new QWidget()) ;
vector<Controls> g ;
g.push_back(Controls(layout , "WHITE_BALANCE_RED_V" , 56 ));
Panel.get()->setLayout(&layout);
Panel.get()->show();
return app.exec();
}
编辑:
我从 ~controls 中删除auto_ptr析构函数,当我再次运行它时,我得到这个异常
pure virtual method called
terminate called without an active exception
- 我初始化了滑块并在复制构造函数中旋转
这里有两件"奇怪"的事情,都与auto_ptr有关。
第一种是成员析构函数在嵌入程序析构函数的退出后自动调用。因此,显式销毁 meber 变量会导致"双重销毁",这是编译器无法管理的内容。
(注意:变量被称为"指针"这一事实不会使它成为变量:如果使用原始指针,并且调用delete pointer
不会破坏 pointe-r,而是破坏pointe-d,这是auto_ptr自己做的事情)。
第二个是auto_ptr
是不可复制的:实际上它使用复制运算符来实现移动语义,但是......容器(如 std::vector)假设副本是...复制(而不是移动)。
在大多数std::vector
(以及 std::list)实现中,这不是问题,因为实现者关注这一点并避免他们的容器同时生成存在的副本。但是一些突变算法无法始终如一地工作,仅仅是因为它们无意中"移动"到错误的地方——函数返回后将被摧毁的地方......嘶!
第二个方面由 C++11 解决,通过实现支持可复制和可移动元素的容器(C++11 配备了 r 值引用,复制和移动是很好的区分操作)并弃用auto_ptr
以支持unique_ptr
,实现"移动"不是">上面的复制"而是">代替复制"。
故事的寓意:在C++11中使用unique_ptr
而不是auto_ptr
。
在 C++03 中,不要在容器或必须留在容器中的对象中使用auto_ptr
。
使用原始指针并定义适当的(针对您的对象)复制语义(通过执行"深层复制",复制指向指向对象副本的指针)或共享语义(通过使指针指向指向相同的对象,并管理引用计数以触发指向元素的销毁。 boost::shared_ptr 就是这种"指针"的一个例子)
程序运行没有错误,但现在控件正在创建!
这实际上很奇怪,因为在Controls::Controls(const Controls ©)
中,您正在调用将返回 0 的this->Slider.get()
,因为您的成员尚未初始化。
首先,您需要阅读并了解如何使用auto_ptr
。
其次,你应该忘记auto_ptr
,永远不要进一步使用它。Qt有自己的智能指针,但在你的情况下不需要它们,因为QObjects管理着他们孩子的生命周期。
因此,第三,阅读有关Qt中的内存管理的信息,并完全摆脱所有这些智能指针。
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 迭代时从向量和内存中删除对象
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 如何创建从同一类继承的不同对象的向量
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 从多个源构造一个对象,包括一个对象向量
- 在C 中,是否有可能在不兼容类型的std ::向量对象之间传输不同类型的缓冲区
- 将向量对象存储在共享指针投掷错误中
- E0312,C2664尝试将向量对象作为函数参数传递时错误
- 相对于向量对象的两个成员,找到两个向量的相交的有效方法
- 将数据从文件读取到向量对象
- C 向量对象访问
- 向量对象声明后的括号是什么意思
- 2向量对象指向相同的分配内存
- 如何返回向量对象
- 传递单个或向量对象时没有重载函数的实例
- 指向数组和向量对象的指针
- 向量对象库,可以存储其他对象类型的对象
- 如何从另一个向量/对象集构造新的向量/指针集