一面阿里广告营销部门的引擎架构团队


一面阿里广告营销部门的引擎架构团队

面的是研发工程师C/C++

没回答上来的问题

  1. C++的几种构造函数

    • 默认构造函数
    • 普通构造函数
    • 复制构造函数(拷贝构造函数)
    • 赋值构造函数(转换构造函数)
  2. C++类成员的初始化顺序是按照初始化列表的顺序进行初始化的吗

    是严格按照成员变量的声明顺序进行初始化的。

    1
    2
    3
    4
    class Node {
    int a, b;
    Node(int aa, int bb) : b(bb), a(aa) {}
    };

    在这种情况下,是先初始化 $a$ ,再初始化 $b$ 。

  3. 复制构造函数为什么参数必须是引用类型的

    如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式,而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。因此拷贝构造函数的参数必须是一个引用。

  4. 写代码的时候需要new一个数组,但是我忘记了如何使用new进行申请一段连续的空间。

    1
    2
    3
    4
    5
    6
    7
    int *a = new int;
    int *b = new int(4);//赋值为4
    int *c = new int[5];//申请长度为5个int的空间

    delete a;
    delete b;
    delete[] c;

问的问题

  1. 语言方面

    • 对C++中static关键字的理解
    • 对C++中各种构造函数的理解
    • 对C++中类的继承的理解
    • 以及多态的用法
  2. 操作系统方面

    • 关于虚拟内存从上到下排序啥的?(不太记得了)

      我当时回答是还没学到这一块。

    • 关于多线程同时改变一个变量?(好像是)

      我的回答是使用互斥锁,然后问我还有什么方法,我说可能还有信号,但是我只用过互斥锁。

    • 关于一个场景,多个人需要从一个地方进行读和写,如何实现多个人同时进行读,并且有人写的时候没有人读。

      我的回答是使用信号,比如semaPsemaV这种的信号调用。就是在cs162课程中第9节课讲到的具体例子。接着对这个场景的实现进行了详细的描述。

  3. 现场编程

    • 给了一个场景,如果要实现一个string类,使用的是一段连续的空间,并且只有两个变量:这段连续空间的首地址、长度。

      写一个构造函数。

      写一个复制构造函数。

      刚开始在用new进行申请空间,但是写着写着忘了怎么用new申请一段连续的空间了,就跟面试官说忘了怎么使用new了,因为最近使用的一直是malloc进行申请空间,然后面试官就让我用malloc进行实现了,并且还提醒了我使用配套的函数进行空间的释放。

      然后写完这部分之后问我有没有什么bug,然后给我说了一个场景,a = a的时候会出问题,会把原本的空间给释放掉。

      写一个赋值构造函数。

      我当时不记得赋值构造函数是什么了,就没写。

      然后问我为什么写复制构造函数的时候必须使用引用变量,我没回答出来。

      我当时写的

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      class my_string {
      private:
      char *st;
      int len;
      public:
      my_string() {
      st = nullptr;
      len = 0;
      }
      my_string(mystring &s) const {
      if(this->st == s.get_st())
      return;
      if(st != nullptr)
      free(st);
      // this->st = new char[s.get_len()];
      this->st = (char*)malloc(sizeof(char) * s.get_len());
      this->len = s.get_len();
      // strcpy(this->st, s.get_st());
      for(int i = 0; i < len; ++i) {
      this->st[i] = s.get_st()[i];
      }
      }

      char* get_st() {
      return st;
      }
      int get_len() {
      return len;
      }
      };
    • 给出两个有序的单向链表,把这两个链表合并成为一个链表,并保持有序。

      提醒了我如果一个链表已经结束,就可以直接break掉了。

      当时写的

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      class Node {
      public:
      int val;
      Node *next;
      };

      Node *merge(Node *a, Node *b) {
      if(a == nullptr) {
      if(b == nullptr) {
      return nullptr;
      }
      return b;
      }
      else if(b == nullptr) {
      return a;
      }

      Node *ret, *now;
      if(a->val < b->val) {
      now = ret = a;
      a = a->next;
      }
      else {
      now = ret = b;
      b = b->next;
      }

      while((a != nullptr) || (b != nullptr)) {
      if(a == nullptr) {
      now->next = b;
      break;
      // now = b;
      // b = b->next;
      // continue;
      }
      else if(b == nullptr) {
      now->next = a;
      break;
      // now = a;
      // a = a->next;
      // continue;
      }

      if(a->val < b->val) {
      now->next = a;
      now = a;
      a = a->next;
      }
      else {
      now->next = b;
      now = b;
      b = b->next;
      }
      }

      return ret;
      }
    • 问了一下关于二叉树的几种遍历方式,然后说还有一种遍历方式是按层来遍历,然后我简单说了一下实现方法,说还没有写过这种的,然后就让我现场实现一下。

      这一部分没有什么问题。

      当时写的代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      class tree_node {
      public:
      int val;
      tree_node *left, *right;
      }

      void func(tree_node *root) {
      if(root == nullptr)
      return;

      queue<tree_node*> q;
      q.emplace(root);

      while(!q.empty()) {
      tree_node *now = q.front();
      q.pop();

      printf("%d ", now->val);

      if(now->left != nullptr) {
      q.emplace(now->left);
      }
      if(now->right != nullptr) {
      q.emplace(now->right);
      }
      }
      printf("\n");

      return;
      }

总结

最后面试官给我介绍了他们部门和他们团队主要是做什么的,然后问了我之后是否要考研,然后是问我还有什么问题没有,让我进行提问。


文章作者: Shaun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Shaun !
评论
  目录