指针和地址
Pointers and addresses
我只是在玩一点反射,我看到一些对我来说没有意义的东西。应用程序基本上要求您输入一个类的名称,如果在映射中找到它,它就创建该类的一个实例,并打印出对象的地址。
第一次i在Derived1中键入时,它生成一个地址例如(0x00001),第二次i在相同的名称中键入时,它显示另一个地址(0x00002),第三次它再次使用相同的地址。
为什么我只得到第二个对象的新地址,而不是其他对象的新地址?
这根本不是问题,我只是好奇。
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <vector>
#include <typeinfo>
class Base
{
protected:
int id;
public:
Base(int _id)
:id(_id)
{
std::cout << "Im the base class, and this is my address: " << this << std::endl;
}
virtual void PrintMyAddress() const = 0;
void PrintId()
{
std::cout << "This is my ID: " << this->id << std::endl;
}
virtual ~Base(){}
};
class Derived1 : public Base
{
public:
Derived1(int _id) : Base(_id){}
void PrintMyAddress() const override
{
std::cout << "I'm derived 1, this is my address: " << this << std::endl;
}
~Derived1(){}
};
class Derived2 : public Base
{
public:
Derived2(int _id) : Base(_id){}
virtual void PrintMyAddress() const override
{
std::cout << "I'm derived 2, this is my address: " << this << std::endl;
}
virtual ~Derived2(){}
};
class Derived3 : public Derived2
{
public:
Derived3(int _id) : Derived2(_id){}
void PrintMyAddress() const override
{
std::cout << "I'm derived 3, this is my address: " << this << std::endl;
}
~Derived3(){}
};
class Generate
{
private:
typedef std::unique_ptr<Base> (Generate::*SomeFunction)(int);
std::map<std::string, SomeFunction> listFunction;
public:
Generate()
{
this->MapClasses();
}
template <typename T>
std::unique_ptr<Base> CreateDerived(int _id)
{
std::unique_ptr<Base> tmp(new T(_id));
return std::move(tmp);
}
void MapClasses()
{
this->listFunction["Derived1"] = &Generate::CreateDerived<Derived1>;
this->listFunction["Derived2"] = &Generate::CreateDerived<Derived2>;
this->listFunction["Derived3"] = &Generate::CreateDerived<Derived3>;
}
std::unique_ptr<Base> Class(std::string _name)
{
if (this->listFunction.find(_name) != this->listFunction.end())
{
return std::move((this->*this->listFunction[_name])(rand() % 100));
}
else
{
std::unique_ptr<Base> itsnull;
return std::move(itsnull);
}
}
std::map<std::string, SomeFunction>& GetFunctionList()
{
return this->listFunction;
}
};
int main()
{
Generate gen;
bool run = true;
while (run)
{
std::cout << std::endl << "What class do you want to generate? Type in the name of the class: " << std::endl << std::endl;
std::string className;
std::cin >> className;
if (className == "exit")
{
run = false;
continue;
}
auto genclass = gen.Class(className);
if (genclass.get())
{
genclass->PrintMyAddress();
genclass->PrintId();
std::cout << "This is my TypeID: " << typeid(*genclass).name() << std::endl;
}
else
{
std::cout << "Class couldn't be created because it doesn't exist..." << std::endl;
}
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'n');
return 0;
}
这是一个类似的例子,但总是显示相同的地址:
for (int i = 0; i < 10; ++i)
{
int* test = new int;
std::cout << test << std::endl;
delete test;
}
编译器在第二次创建后优化一切吗?
你的代码基本上创建了一个新对象,然后在每个循环中删除它。
对象的地址取决于堆把它放在哪里。堆可以自由地重用最近释放的空间(如果不这样做就太愚蠢了),所以你很可能会得到重复的地址。
当我用gcc 4.9.0测试Linux上的代码并要求Derived1 3次时,我总是获得相同的地址(例如0xdead)原因是编译器替换了
行auto genclass = gen.Class(className);
std::unique_ptr<Base> genclass = gen.Class(className);
当执行到while循环结束时,局部变量genclass被销毁
unique_ptr通过删除它所指向的对象来完成它的工作,从而使地址0xdead可用
下一次迭代将创建一个新对象并重用0xdead地址,因为它是可用的
在您的情况下,内存分配机制可能略有不同,地址仅在第三次迭代时可用
您可以通过在基析构函数中添加断点或在析构函数中添加如下指令来检查unique_ptr执行的对象的析构:
std::cout << "Delete base whose address is " << this << std::endl;
相关文章:
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 将地址分配给本地指针后,公共对象的变量将消失
- 为什么指针不写入类的地址?
- CUDA:统一内存和指针地址的更改
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 如何从绝对地址的 C 样式指针创建对C++对象的引用
- 当我在 C++ 中将派生类的指针分配给指针时,地址会更改
- 是否可以仅通过将分配的指针地址存储在C++中来分析内存?
- 如何在程序集函数中将元素数组作为参数传递时转发 ARM 寄存器的地址指针
- 如何使用构造函数初始化内存地址(指针变量)?
- 数组基础地址指针
- 如何在不使用返回的情况下从函数获取变量的地址(指针)
- 保存QWidgets的地址/指针
- C++ 读取内存地址/指针和偏移量
- 从存储在 CTreeCtrl 的 LPARAM 中的结构中检索地址/指针 (IXMLDOMNode*) - 不起作用
- 简单的C++地址/指针澄清
- 如何获取成员函数的地址指针
- 当“按引用传递”成为强制传递而不是按地址/指针传递时
- C++ 为什么不是同一个地址(指针)