static_cast是否会使编译器分配的空间比新操作符要分配的空间还要大?

问题描述 投票:2回答:1

我已经用各自的数据成员编写了Base类和Derived类,如下面的代码所示。现在在主函数中,我使用static_cast创建了由Derived类指针指向的新Base类对象。

#include <iostream>
#include <vector>
class Base {
public:
  int b;
  Base() : b(2){};
  int get_b() const;
};

class Derived : public Base {
public:
  int d;
  Derived() : d(4){};
  int get_d() const;
};

int Base::get_b() const { return b; }

int Derived::get_d() const { return d; }

int main() {
  std::vector<Derived *> bArray;
  bArray.push_back(static_cast<const Derived *>(new Base()));
  bArray.push_back(static_cast<const Derived *>(new Base()));

  std::vector<Derived *>::iterator bArrayIt = bArray.begin();
  for (; bArrayIt != bArray.end(); ++bArrayIt) {
    std::cout << (*bArrayIt)->get_b() << std::endl;
    std::cout << (*bArrayIt)->get_d() << std::endl;
  }
}

输出

2
0

现在在代码中,我尝试使用Derived指针访问derived类的数据成员,但我希望它返回编译错误或'ArrayOutOfBoundIndex'或segmentation_fault,因为对象是< [Base type,因为仅为基础对象分配了空间,但是该成员'd'的值为零。根据我对static_cast的了解,它只是更改指针类型而不分配内存,但是在这里,我们不仅可以访问未分配的内存,而且该值最初已预先设置为0,所以我做了一个小实验我自己的。

#include <iostream> #include <string.h> class State; class Base; class Derived; class State { public: static bool flag; }; bool State::flag = true; class Base : public State { public: int a; int b; int c; Base() : a(2), b(4), c(16){}; int get_a() { return a; } int get_b() { return b; } int get_c() { return c; } }; class Derived : public Base { public: int d; int e; int f; Derived() : d(6), e(8), f(12){}; int set_d(int ds) { d = ds; } int get_d() { return d; } int get_e() { return e; } int get_f() { return f; } }; int main() { Derived *d[2]; d[0] = static_cast<Derived *>(new Base()); d[1] = static_cast<Derived *>(new Base()); std::cout << d[0]->get_a() << std::endl; std::cout << d[0]->get_d() << std::endl; d[0]->set_d(100); std::cout << d[0]->get_d() << std::endl; int *i = reinterpret_cast<int *>(d[0]); std::cout << (*i) << std::endl; i++; std::cout << (*i) << std::endl; i++; std::cout << (*i) << std::endl; i++; std::cout << (*i) << std::endl; i++; std::cout << (*i) << std::endl; i++; std::cout << (*i) << std::endl; std::cout << "Let's move onto d[1]" << std::endl; int *j = reinterpret_cast<int *>(d[1]); std::cout << (*j) << std::endl; j++; std::cout << (*j) << std::endl; j++; std::cout << (*j) << std::endl; j++; std::cout << (*j) << std::endl; j++; std::cout << (*j) << std::endl; j++; std::cout << (*j) << std::endl; return 0; }

输出

2 0 100 2 4 16 100 0 0 Let's move into d[1] 2 4 16 0 0 0
输出是根据我之前得到的。

我的问题

    为什么允许该变量访问new关键字或编译器未分配的内存,以及如何做到这一点?
  1. 如果能够访问内存位置,为什么编译器不给出任何运行时错误或编译时错误,并且有什么方法可以使编译器这样做?
  2. 现在,如果内存是由编译器分配的,或者以某种方式分配给内存,它将对内存产生什么影响,即如果基类为12个字节,派生类为24个字节,那么将创建基类型并使用static_cast的每个对象为它由派生指针指向将分配24个字节的内存?
c++ pointers inheritance memory static-cast
1个回答
-1
投票
第一个代码示例未在最新的gcc中编译(从static_cast中删除const使其可以工作)。

std::vector<Derived *> bArray; bArray.push_back(static_cast<const Derived *>(new Base()));在上面的代码中,您创建了一个Derived类型的向量,然后创建Base类型,并告诉编译器“好像它是派生类型”一样插入它。此时,成员os派生类型尚未定义,因此事实>>

std::cout << (*bArrayIt)->get_d() << std::endl;

返回0是您的运气(或运气不好)。当您访问RAM中靠近程序的内存时,您可能不会破坏任何内容,但是正如其他人指出的那样,这是UB。编译器不会阻止您这样做,因为这将需要一些运行时检查(这会使程序变慢),并且您可能会或可能不想使用(不支付不使用规则)[]
© www.soinside.com 2019 - 2024. All rights reserved.