在 Debug 版本下,编译器通常会为类的成员变量赋予一些方便调试的初始值,以帮助开发者发现潜在的问题。对于指针类型的成员变量,Debug 版本的编译器一般会将它们初始化为一个特定的值,例如:
- **全局/静态指针变量**:通常会被初始化为 `nullptr`,即空指针常量。
```cpp
class Example {
public:
static int* staticPtr; // 静态指针成员变量,在 Debug 模式下通常初始化为 nullptr
};
int* Example::staticPtr = nullptr; // 静态成员变量定义并初始化为 nullptr
```
- **非静态指针变量**:在类的非静态成员变量中声明的指针,Debug 版本的编译器也可能会初始化为 `nullptr` 或者一些特定的标记值,以帮助开发者识别未初始化的指针。
```cpp
class Example {
public:
int* ptr; // 非静态指针成员变量,通常在 Debug 模式下初始化为 nullptr
};
void foo() {
Example obj;
// obj.ptr 在 Debug 模式下通常初始化为 nullptr
}
```
这种行为有助于在调试过程中发现未初始化的指针,因为未初始化的指针可能导致程序运行时的不可预测行为,如段错误或者崩溃。
总结来说,在 Debug 版本下,编译器会更倾向于对指针进行安全初始化,以帮助开发者发现和调试潜在的问题,而在 Release 版本下,则可能不会生成初始化指针的代码,以提高执行效率。
在 C++ 中,如果在类中声明了指针类型的成员变量但没有显式初始化它们,并且在 Release 模式下编译,编译器不会自动为指针赋予一个特定的初始值。指针的初始值在未显式初始化时是不确定的,它们将包含任意的垃圾值(garbage value),这取决于内存中的随机数据。
具体来说:
1. **全局/静态指针变量**:如果是全局或静态成员指针变量,它们会被初始化为 `nullptr`,即空指针常量。
```cpp
class Example {
public:
static int* staticPtr; // 静态指针成员变量,自动初始化为 nullptr
};
int* Example::staticPtr = nullptr; // 静态成员变量定义并初始化为 nullptr
```
2. **非静态指针变量**:对于在函数或类的非静态成员变量中声明的指针,如果没有显式初始化,它们的值是未定义的(unspecified),通常是随机的垃圾值。在 Release 模式下,编译器可能会不生成初始化指针的代码,因此它们可能会包含未知的内存地址。
```cpp
class Example {
public:
int* ptr; // 非静态指针成员变量,未初始化
};
void foo() {
Example obj;
// obj.ptr 的值在 Release 模式下是未定义的
}
```
在实际开发中,为了避免悬挂指针(dangling pointers)和不可预测的行为,建议在声明指针类型的成员变量时,始终在构造函数中显式初始化它们为 `nullptr` 或者指向有效内存地址。这样可以确保在使用指针前它们已经被正确初始化。
eg:
template <typename T>
class UTILITY_API TDataColumn
{
public:
TDataColumn() : _column_name(QString()), _caption(QString()){};
TDataColumn(const QString& column_name) : _column_name(column_name), _caption(QString()){};
TDataColumn(const QString& column_name, QVariant::Type column_type) : _column_name(column_name), _type(column_type){};
virtual ~TDataColumn(){};
public:
void Caption(const QString& caption) { _caption = caption; } //设置列的标题
QString Caption() const { return _caption.size() ? _caption : _column_name; } //获取列的标题
void ColumnName(const QString& column_name) { _column_name = column_name; } //设置 DataColumnCollection 中的列的名称
QString ColumnName() const { return _column_name; } //获取 DataColumnCollection 中的列的名称
void Value(const T& value) { _value = value; } //获取值
T Value() const { return _value; } //设置值
void Table(DataTable* p_table){ _table = p_table; } //设置列所属的 DataTable
DataTable* Table() const { return _table; } //获取列所属的 DataTable
QVariant::Type DataType() const { return _type;} //获取存储在列中的数据的类型
void DataType(QVariant::Type column_type) { _type = column_type;} //设置存储在列中的数据的类型
protected:
QString _column_name; //列名
QString _caption; //列的标题
T _value; //值
QVariant::Type _type; //列的数据类型
DataTable* _table; //列所属DataTable
};
设计此类,并没有给_table赋初始值
release版本下,编译器会赋垃圾值,有的值可能是其他DataTable*实例化的地址。导致
DataColumn* dc_tmp = new DataColumn(header_record.field(i).name(), header_record.field(i).type());//初始化_table未赋初始值
_dc_collect->Add(dc_tmp); //Add实现如下:
void DataColumnCollection::Add(DataColumn *p_column, int index)
{
if (p_column == nullptr){
qDebug() << "p_column == nullptr";
return;
}
qDebug() << this->_table;
if (p_column->_table != nullptr) qDebug() << p_column->_table;
if ((p_column->_table != nullptr) && (p_column->_table == this->_table)){
qDebug() << "p_column->_table != nullptr && p_column->_table == this->_table" ;
return;
}
}
p_column->_table本该是nullptr却被编译器赋了this->_table的值。故判断条件出错。