C++ 如何防止临时文件超出范围?
在以下情况下,我的对象超出范围,访问了无效指针:C++ 如何防止临时文件超出范围?,c++,vector,scope,copy,raii,C++,Vector,Scope,Copy,Raii,在以下情况下,我的对象超出范围,访问了无效指针: struct Animal { char* buffer; Animal() { buffer = new char[100]; } ~Animal() { delete[]buffer; } }; int main() { vector<Animal> list; { Animal dog; list.push_back(dog); }
struct Animal
{
char* buffer;
Animal() { buffer = new char[100]; }
~Animal() { delete[]buffer; }
};
int main()
{
vector<Animal> list;
{
Animal dog;
list.push_back(dog);
}
list[0].buffer[50] = 7; // Buffer's been deleted, can't access it
}
但这仍然会创建一个临时的,除非对它进行优化,我不希望依赖它,因为在另一个地方(另一个编译器),它可能不会做同样的事情
编辑:多亏了Remy Lebeau,我了解到您可以直接在向量中构造向量元素,无需临时设置,无需复制,功能如下:
template< class... Args >
void emplace_back( Args&&... args );
模板
空侵位返回(Args&…Args);
我不知道可变模板参数是如何工作的,但描述如下:
将新元素追加到容器的末尾。元素是
通过std::allocator\u traits::construct构造,通常
使用“新放置”在该位置在位构造图元
由集装箱提供。参数args。。。已转发至
构造函数作为std::forward(args)
问题不在于临时措施超出了范围。真正的问题是,
Animal
没有实现复制构造函数或复制赋值操作符,从而违反了
当您将临时对象推入向量时,会生成对象的副本,但编译器生成的副本构造函数只是按原样复制指针,而不会分配内存的副本。因此,当临时文件被销毁时,内存将在析构函数中解除分配,副本将保留一个指向无效内存的悬空指针
添加复制构造函数以分配新内存:
struct Animal
{
char* buffer;
Animal() {
buffer = new char[100];
}
Animal(const Animal &src) {
buffer = new char[100];
std::copy(src.buffer, src.buffer+100, buffer);
}
~Animal() {
delete[] buffer;
}
Animal& operator=(const Animal &rhs) {
if (this != &rhs) {
std::copy(rhs.buffer, rhs.buffer+100, buffer);
}
return *this;
}
};
或者,使用std::vector
代替原始指针,让编译器为您生成合适的复制构造函数、复制赋值运算符和析构函数:
struct Animal
{
std::vector<char> buffer;
Animal() : buffer(100) {}
};
问题不在于临时措施超出了范围。真正的问题是,
Animal
没有实现复制构造函数或复制赋值操作符,从而违反了
当您将临时对象推入向量时,会生成对象的副本,但编译器生成的副本构造函数只是按原样复制指针,而不会分配内存的副本。因此,当临时文件被销毁时,内存将在析构函数中解除分配,副本将保留一个指向无效内存的悬空指针
添加复制构造函数以分配新内存:
struct Animal
{
char* buffer;
Animal() {
buffer = new char[100];
}
Animal(const Animal &src) {
buffer = new char[100];
std::copy(src.buffer, src.buffer+100, buffer);
}
~Animal() {
delete[] buffer;
}
Animal& operator=(const Animal &rhs) {
if (this != &rhs) {
std::copy(rhs.buffer, rhs.buffer+100, buffer);
}
return *this;
}
};
或者,使用std::vector
代替原始指针,让编译器为您生成合适的复制构造函数、复制赋值运算符和析构函数:
struct Animal
{
std::vector<char> buffer;
Animal() : buffer(100) {}
};
我不明白这个问题。你是在要求你把那些不是默认可构造的东西放入
std::vector
?这不是reserve()
所做的。“然后我使用我的vectorofamals[0]并访问一个无效指针”你说的“无效指针”是什么意思?它在哪里?对不起,我最好重写一下question@TitoneMaurice您希望通过使用vector来防止这些问题,但在我看来,只关注vector是错误的。向量刚刚暴露了你的类的问题。解决复制问题(很容易通过使用<代码> STD::vector < /COD>或std::vector
?这不是reserve()
所做的。“然后我使用我的vectorofamals[0]并访问一个无效指针”你说的“无效指针”是什么意思?它在哪里?对不起,我最好重写一下question@TitoneMaurice您希望通过使用vector来防止这些问题,但在我看来,只关注vector是错误的。向量刚刚暴露了你的类的问题。要么修复复制问题(很容易通过使用<代码> STD::vector < /COD>或emplace\u back()
而不是push\u back()
。但是,当一个类管理不能浅层复制的资源时,仍然应该遵循三的规则(以及C++11及更高版本中的五的规则)。vector::emplace_back()不起作用。当我执行myVector.emplace_back(myStruct(arg1,arg2));它首先构造myStruct,然后copy在向量中构造一个新的。一次只做一件事。如果emplace_back()不起作用,我想我应该问一个问题。@TitoneMaurice删除显式临时变量,只需自己传递构造函数参数:myVector.emplace_back(arg1,arg2)代码>emplace\u back()
将在原地构造新对象时将参数转发给类型构造函数。谢谢。这是我不清楚的过错。我想学习如何避免复制。我认为有很多方法可以在向量中构造一个对象。@TitoneMaurice你的问题中没有任何东西暗示你的目标是避免复制。在C++11之前,您无法避免复制。在C++11及更高版本中,您可以使用emplace\u back()
而不是push\u back()
。但是,当一个类管理不能浅层复制的资源时,仍然应该遵循三的规则(以及C++11及更高版本中的五的规则)。vector::emplace_back()不起作用。当我执行myVector.emplace_back(myStruct(arg1,arg2));它首先构造myStruct,然后copy在向量中构造一个新的。一次只做一件事。如果emplace_back()不起作用,我想我应该问一个关于