先看一段代码:
#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可以...
5. **nullptr**:`nullptr`是C++11引入的新的空指针常量,解决了`NULL`和`0`在不同场景下可能引发的混淆问题。 6. **初始化列表(Initializer Lists)**:初始化列表允许在构造函数中以更直观的方式初始化对象,...
文章中提供了一个C++示例代码,虽然这段代码是为了说明`static`在C++中的作用,但我们可以从中了解到一些关键概念: ```cpp void staticLocalVar() { static int a = 0; // 只初始化一次,在函数首次调用时 cout ...