先看一段代码:
#include <cstddef>
#include <cstdio>
#include <iostream>
using namespace std;
class TestSS;
class TestStaticMember {
public:
static TestSS* ssptr;
};
TestSS* TestStaticMember::ssptr = NULL;
class TestSS{
private:
int version;
public:
TestSS(){
version = 1;
cout << "TestSS constructor..." << endl;
}
~TestSS(){
cout << "TestSS deconstrcutor..." << endl;
//delete version;
}
void setVersion(const int ver){
version = ver;
}
int getVersion() const {
return version;
}
};
void init(){
TestSS ss;
TestStaticMember::ssptr = &ss;
ss.setVersion(111);
printf("In init: %p, %p\n", &ss, TestStaticMember::ssptr);
cout << "In init: " << TestStaticMember::ssptr->getVersion() << endl;
}
int main(int argc, char** argv){
init();
printf("In main: %p\n", TestStaticMember::ssptr);
cout << "In main: " << TestStaticMember::ssptr->getVersion() << endl;
return 0;
}
在我的环境,Linux 64位,编译器(g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4))
结果输出:
TestSS constructor...
In init: 0x7fff82029e50, 0x7fff82029e50
In init: 111
TestSS deconstrcutor...
In main: 0x7fff82029e50
In main: 111
因为我同事提供给我的一个API与这个类似,且告诉我这样调用,猛一看觉得有问题,于是写了上面的测试代码。但是输出结果出乎我的意料,一时间还以为我对于变量作用域理解有误或者是编译器对static成员做了特殊处理,于是上网搜各种资料,结果是 编译器不保证能正确访问被释放的内存了,即结果是不确定的,如果原来内存里面的值还没被擦除或覆盖就可能读出原来的值。于是疑惑解决了,真实蛋疼。
分享到:
相关推荐
如命名空间(namespace)、类成员(Class members)、成员函数(Member Functions)、静态成员函数(Static Member Functions)、联合(Unions)、位字段(C++ Bit Fields)、嵌套类声明(Nested Class Declarations...
《luabind派生C++类及相关问题》 在C++和Lua的交互中,luabind库提供了一种在Lua中派生C++类的能力,从而实现了在脚本语言中利用多态性的功能。根据luabind的文档,我们可以看到这种机制允许在Lua中创建C++类的子类...
总结来说,C++的类静态成员提供了一种管理全局数据的有效方法,它可以避免全局变量带来的许多问题,同时提供了更好的封装和控制。在设计软件时,尤其是在处理共享数据时,应优先考虑使用静态成员来实现全局数据管理...
如果尝试通过`pd2`访问`D`类独有的成员函数,就可能会引发访问违规。 - **示例2**:考虑另一种情况,仅提供基类指针。 ```cpp void g(B* pb) { D* pd1 = dynamic_cast*>(pb); // 动态类型检查 D* pd2 = static_...
本笔记总结了Effective C++的第1到第11条款,涵盖了C++语言的多个方面,包括构造函数、拷贝构造函数、拷贝赋值函数、const关键字、enum、inline函数、定义域、static变量、初始化、编译器生成的函数、拷贝控制、多态...
首先,我们要理解C++的内存层次结构,主要包括栈内存(Stack)、堆内存(Heap)、静态存储区(Static)和常量存储区(ReadOnly)。栈内存用于存储局部变量和函数调用信息,由编译器自动管理;堆内存是程序员通过`new...
类可以包含命名空间(namespace)、类名(class names)、成员变量(class members)、成员函数(member functions)、静态成员函数(static member functions)、联合体(union)、位域(C++ Bit Fields)、嵌套类(nested class ...
如果C代码在C++对象被销毁后仍然尝试回调,将会导致悬挂指针,从而引发未定义行为。 在实际项目中,可能还需要考虑多线程环境下的同步问题,以及异常安全的实现。例如,可以使用智能指针(如`std::shared_ptr`)来...
在C++类中,`static`关键字用于声明静态成员变量或成员函数。静态成员属于类,而不是类的实例,所有类的对象共享同一份静态成员变量的拷贝。静态成员函数不能访问非静态成员,因为它们不与特定的对象关联。例如: `...
然而,使用static需要注意其可能带来的副作用,如破坏程序的可重复性(因为内存中的值会保留),以及可能导致的并发问题(在多线程环境中,静态变量的全局性可能引发竞争条件)。 总结来说,static关键字在C++编程...
缺点则是容易引发内存泄漏、野指针等问题。例如,忘记释放不再使用的内存或者错误地访问已经被释放的内存,都可能导致程序崩溃或行为异常。 **解决方案**:采用智能指针如`std::shared_ptr`和`std::unique_ptr`可以...
此应用旨在通过具体的类(如`Animal`、`Birds`、`Fish`、`Reptile`等)展示C++中的面向对象特性,包括虚基类、派生类、虚函数、多继承以及如何消除二义性等问题。此外,还涉及了静态数据成员和静态成员函数的概念。 ...
《C++程序设计陷阱》是一本深入探讨C++编程中潜在问题的专业书籍,旨在帮助开发者避免常见的编程陷阱和误区。该书分为中英文两个版本,分别以PDF和CHM格式提供,为不同语言习惯的读者提供了便利。 1. **命名空间与...
在C++中,类型转换是编程中不可或缺的一部分,特别是在处理多态性时。`dynamic_cast`和`static_cast`是两种不同的类型转换操作符,它们各自适用于不同的场景。本文将通过示例详细解释它们的使用方法,特别是它们在...
在C、C++和Objective-C这三种语言混合编程时,头文件管理成为一个关键问题,特别是在Xcode这样的集成开发环境中。由于Objective-C++是Objective-C和C++的融合,它可以处理C和C++的代码,因此将文件扩展名改为.mm可以...
在C++中有多种类型转换的方式,包括隐式转换(如自动类型提升)、显式转换(如使用`static_cast`、`dynamic_cast`等)。正确地使用类型转换可以避免类型不匹配引发的编译错误或运行时错误。 #### 3. 函数 ##### ...
5. **nullptr**:`nullptr`是C++11引入的新的空指针常量,解决了`NULL`和`0`在不同场景下可能引发的混淆问题。 6. **初始化列表(Initializer Lists)**:初始化列表允许在构造函数中以更直观的方式初始化对象,...
文章中提供了一个C++示例代码,虽然这段代码是为了说明`static`在C++中的作用,但我们可以从中了解到一些关键概念: ```cpp void staticLocalVar() { static int a = 0; // 只初始化一次,在函数首次调用时 cout ...