从复制构造函数外部修改对象成员时导致向量内存损坏,但从复制构造函数内部修改时不会
C++: vector memory corruption when modifiying an object member from outside the copy constructor but not when modifying from within
#include <iostream>
#include <vector>
#include <cassert>
class a_class
{
public:
int num_IN;
a_class():num_IN(0){}
a_class(a_class const & origin){/*Initialise();*/} //if not called here, error occurs
void Initialise(){num_IN =5;}
};
int main ()
{
std::vector <a_class> the_vector;
for(int q=0; q < 30; q++)
{
the_vector.push_back(a_class());
the_vector[q].Initialise();
assert(5 == the_vector[q].num_IN); //no problem here
}
for(int q=0; q < 30; q++)
assert(the_vector[q].num_IN == 5); //assertion fails
}
我不明白从外部调用和在CC内部调用之间的区别,我也不知道为什么它在任何情况下都会引起问题。
std::vector
可能会重新分配它使用的缓冲区,如果它的大小超过它,在这种情况下,它必须将旧元素复制到新的缓冲区。如果没有合适的复制构造函数来复制num_IN
,则旧值将丢失。
通过提供一个正确的复制构造函数来修复这个问题:
a_class(a_class const & origin) : num_IN(origin.num_IN) {}
在上面的代码中,复制构造函数甚至是不需要的——如果你不提供,编译器会在这里生成一个合适的。
当您重复调用push_back()
以附加新元素时,std::vector
类可能必须重新分配底层动态数组。通常的策略是std::vector
将底层缓冲区的大小增加一个因子,可能是2
的一个因子。
当这种重新分配发生时,将调用复制构造函数(如果使用c++0x
定义了一个构造函数,则调用move构造函数)将vector的元素从旧缓冲区复制到新缓冲区。
你的复制构造函数实际上没有正确复制,你应该分配num_IN
参数:
a_class(a_class const& src): num_IN(src.num_IN) {}
通常,对于STL
容器,存储的数据类型应该遵守"三规则",即构造函数、复制构造函数、赋值操作符和析构函数都可以健壮地一起工作。
在c++0x
中的移动语义,我想这应该扩展到"五规则",因为你还应该考虑适当定义的移动构造函数和移动赋值操作符。
问题是由于push_back
,每当向量的size
增加超过其capacity
时,您的向量在第一个for
循环中重新分配内存。在这个重新分配过程中,vector
通过调用复制构造函数复制其中已经存在的对象。由于您的复制构造函数不正确(您没有在那里做任何事情),因此在重新分配期间不会保留初始化的值。
您的复制构造函数没有做任何事情。应该是num_IN = origin。num_IN;
啊哈,
我能看到发生了什么。
在第一个循环中,将对象压回vector容器,每次压回vector容器时,vector容器的大小都会被调整,并对vector容器中的所有元素调用复制构造函数。由于您已经覆盖了复制构造函数而不做任何事情,因此num_IN未初始化。
使它工作。我将重新启用复制构造函数来执行成员式复制。
或者。
i将把向量的大小调整为所需的大小。这样,vector就不会在每次添加额外元素
时重新调整大小。std::vector <a_class> the_vector;
the_vector.resize(30);
for(int q=0; q < 30; q++)
{
the_vector[q].Initialise();
assert(5 == the_vector[q].num_IN); //no problem here
}
for(int q=0; q < 30; q++)
assert(the_vector[q].num_IN == 5); //assertion fails
- "error: no matching function for call to"构造函数错误
- 修改程序的入口点时未调用全局变量的构造函数
- 如何使用 swig 修改类构造函数以保留对其中一个构造函数参数的引用?
- 为什么从另一个构造函数内部调用C++构造函数不修改类变量?
- 如何在使用 Qt5 构造函数时将非常量参数修改为常量参数?
- 我允许用memcpy(*this)修改构造函数中的所有类成员
- 我的类的可变参数模板构造函数无法修改我的类成员,为什么会这样?
- 当push_back到向量中时,我是否需要复制构造函数来修改静态成员
- 复制构造函数不起作用,无法修改副本
- 在调用基类构造函数之前修改构造函数参数值
- C++ 继承类,并将修改后的参数发送到父级的构造函数
- 是否有可能在构造函数和析构函数之外修改“vptr”
- C++ 如何确保复制构造函数不会修改原始对象的指针数据成员?
- 当我修改复制构造函数以执行一些奇怪的操作,然后按值将对象(该类)传递给函数时会发生什么
- 由算术运算符成员函数修改的动态数组的复制构造函数
- C++ 将字符串传递到构造函数中只会传递" "除非显式修改
- 如何在构造函数中初始化的函数中修改对象大小的2D向量
- 是否可以在constexpr构造函数中修改非静态成员变量(c++ 14)
- 从复制构造函数外部修改对象成员时导致向量内存损坏,但从复制构造函数内部修改时不会
- Qt,在构造函数之外修改小部件属性的问题