图像算法工程面试所做的准备——C++基础篇

【图像类知识学习】图像算法工程师知识储备——究极无敌大总结(二)【深度学习相关】 这篇文章包含了市面常见的图像算法面试题,会在一个月之内列出所有问题,之后的答案慢慢补充 阅读详情

在面试过程中遇到C++相关的问题,有的也是网上搜索的总结,有的贴出原文链接,有的没有贴

1、虚函数和纯虚函数的区别:

 

答:虚函数:为了重载和多态的需要,在基类中是有实现的,virtual void Eat(){……};所以子类中可以重载也可以不重载基类中的此函数   

纯虚函数:就是基类只定义了函数体,没有实现过程,定义方法如: virtual void Eat() = 0; 纯虚函数相当于Java中的接口,自己不去实现,需要子类来实现函数定义;带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重载其虚函数后,才能使用。这样的类也叫抽象类。

2、内联函数和宏定义的差别是什么:

1)内联函数在编译时展开,宏在预编译时展开;

  (2)内联函数直接嵌入到目标代码中,宏是简单的做文本替换;

  (3)内联函数有类型检测、语法判断等功能,而宏没有;

  (4)inline函数是函数,宏不是;

3、重载、继承、多肽都有什么区别:

函数重载:函数名相同,参数不同

对于重载的多个函数来说,其函数名都是一样的,为了加以区分,在编译连接时,C++会按照自己的规则篡改函数名字,这一过程为"名字改编".有的书中也称为"名字粉碎".不同的C++编译器会采用不同的规则进行名字改编

也有运算符重载,实现运算符的加减乘除;

继承:子类可以具有父类的特性,就是继承;但是基类中私有成员无法被继承。

一个派生类继承了所有的基类方法,但下列情况除外:

基类的构造函数、析构函数和拷贝构造函数。

基类的重载运算符。

基类的友元函数(我们说过友元函数不是成员函数)。

有三种继承方式:

公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员(指的是函数)来访问。

保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。(注意:公有成员也变成了保护成员)

私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。(一般都不会使用这种)

封装:

封装的思想就是将实现的细节隐藏,而暴露公有接口;

C++中的访问标识符,可以实现在类中的封装;通常是将所有的成员变量私有化;

尽管看起来访问成员变量的不直接,但使程序更有可重用性和可维护性;

B)隐藏了类的实现,类的使用者只需知道公共的接口,就可以使用该类;

C)封装帮助防止意外的改变和误用;

D)对程序调试有很大的帮助,因为改变类的成员变量只用通过公共接口。

封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用,而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

多态:指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性(也叫静态联编),运行时多态性(动态联编)。 

C++支持两种形式的多态性。第一种是编译时的多态性,称为静态联编。第二种是运行时的多态性,也称为动态联编。运行时的多态性是指必须在运行中才可以确定的多态性,是通过继承和虚函数来实现的。
  a、编译时多态性:通过重载函数实现   采用早绑定:就是在编译时确定对象调用的函数的地址(一般运用于重载)函数多态性
  b、运行时多态性:通过虚函数实现。  采用迟绑定:就会在运行时再去确定对象的类型以及正确的调用函数类的多态性(在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数,此为多态的表现;)( 动态联编要求派生类中的虚函数与基类中对应的虚函数具有相同的名称、相同的参数个数和相同的对应参数类型、返回值或者相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的基类型是基类中虚函数所返回的指针或引用的基类型的子类型。如果不满足这些条件,派生类中的虚函数将丢失其虚特性,在调用时进行静态联编。参考:http://blog.youkuaiyun.com/neiloid/article/details/6934129)

4、预处理和链接库:

答:一个C++程序一般需要经过以下几个步骤才能成为可执行程序:

C++源程序——》编译器预处理——》编译程序——》优化程序——》汇编程序——》链接程序——》可执行程序

编译器预处理:C++编译器自带预处理器,在程序编译之前,由预处理器对C++源程序完成预处理工作。

预处理主要将源程序中的宏定义指令、条件编译指令、头文件包含指令以及特殊符号完成相应的替换工作。

编译程序:以预编译的输出作为输入,利用C++运行库,通过词法分析和语法分析,

在确认所有的指令都符合语法规则时,将其翻译成等价的中间代码表示或者是汇编语言。

优化程序:优化阶段一部分是对中间代码的优化,这种优化不依赖具体的计算机,同机器的硬件环境无关。另一种优化则主要针对目标代码的生成而进行的。对于前一种优化,主要的工作是删除公共表达式、循环优化(循环展开,自动向量化、循环不变量代码移动)以及无用赋值的删除等。

另一种优化同机器的硬件结构密切相关。最主要的是考虑如何充分利用机器的各个硬件寄存器存放有关的变量的值,以减少对于内存的访问次数。

汇编程序:汇编阶段的主要工作是将经过编译、优化后的,以汇编语言的形式存在的程序转化为机器可识别的二进制代码,从而得到相应的目标文件。

链接程序:经历了汇编之后的程序是后缀为.obj形式的文件,仍然是不可执行的,只有经过链接阶段,程序所引用的外部文件关联起来之后,形成.exe后缀的文件之后,才是可执行的。程序中可能引用了定义在其他外部文件中的变量或者函数,比如某些库函数,而链接阶段所做的主要事情就是将这些相关联的文件链接起来,使得所有这些目标文件成为一个能够被操作系统装入执行的统一的整体。

 

动态链接:采用该链接方式表明,需要链接的代码是存放在动态链接库或者某个共享对象的目标文件。

静态链接:采用该链接方式,需要链接的代码会被链接程序从相应的静态链接库中拷贝到可执行程序之中。

5、c++多态底层实现原理

编译器在编译的时候,发现基类中有虚函数,此时编译器会为每个包含虚函数的类创建一个虚表(即vtable),该表是一个一维数组,在这个数组中存放每个虚函数的地址。对于基类和子类都包含了一个虚函数breathe(),因此编译器会为这两个类都建立一个虚表,(即使子类里面没有virtual函数,但是其父类里面有,所以子类中也有了)如下图所示:  

           

那么如何定位虚表呢?编译器另外还为每个类的对象提供了一个虚表指针(即vptr),这个指针指向了对象所属类的虚表。在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。
     正是由于每个对象调用的虚函数都是通过虚表指针来索引的,也就决定了虚表指针的正确初始化是非常重要的。换句话说,在虚表指针没有正确初始化之前,我们不能够去调用虚函数。那么虚表指针在什么时候,或者说在什么地方初始化呢?
      要注意:对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。


    对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。

   需要注意的几点
   总结(基类有虚函数):
     1、每一个类都有虚表。
     2、虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。
     3、派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。

6、指针(pointer)和引用(Reference)的区别:

函数调用时,什么时候采用值传递,什么时候采用引用传递:


如果数据对象很小,如内置数据类型或小型结构,则按值传递。

如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针。

如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需的时间和空间。

如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。

对于修改调用函数中数据的函数:

如果数据对象是内置数据类型,则使用指针。如果看到诸如fixit(&x)这样的代码(其中x是int型),则很明显,该函数将修改x。

如果数据对象是数组,则只能使用指针。

如果数据对象是结构,则使用引用或指针。

如果数据对象是类对象,则使用引用。

 

指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。

int a=1;int *p=&a;

int a=1;int &b=a;

(2)可以有const指针,但是没有const引用;

(3)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(4)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(5)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

(6)"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;

(7)指针和引用的自增(++)运算意义不一样;

7、为什么构造函数不能声明为虚函数、析构函数可以

构造函数不能声明为虚函数的原因是:(why)
1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。

2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初始化,将无法进行。

析构函数设为虚函数的作用:
解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。参考:http://www.cnblogs.com/children/archive/2012/08/13/2636956.html

什么叫基类指针指向派生类:举个例子,定义一个基类Person ,Student继承Person

Person *pt1 = new Person;
Person *pt2 = new Student;          // 用基类的指针指向子类
// Student *pt3 = new Person;     // 不能用子类指针指向基类,错误!
Student *pt4 = new Student;

这个时候delete *pt1 会直接调用Person 的析构函数

delete *pt2,如果Person的析构函数声明为virtual类型,则会先调用Student的析构函数,再调用Person的析构函数,如果Person的析构函数声明不是virtual类型,则只会调用基类Person的析构函数,不会调用Student的析构函数,这样就会导致销毁对象不完全。

结论:最好对着上面链接的例子理解:

可以看出:只有在用基类的指针指向派生类的时候,才会出现这种情况。(ps:为什么只有这种情况呢,在基类中定义了一个虚函数,然后在派生类中又定义一个同名,同参数表的函数,这就是多态。通过一个基类指针来操作对象,如果对象是基类对象,就会调用基类中的那个函数,如果对象实际是派生类对象,就会调用派声类中的那个函数,调用哪个函数并不由函数的参数表决定,而是由函数的实际类型决定。)因为这个时候虚函数发挥了动态的作用。

析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数。如果析构函数不是虚函数,而程序执行时又要通过基类的指针去销毁派生类的动态对象,那么用delete销毁对象时,只调用了基类的析构函数,未调用派生类的析构函数。这样会造成销毁对象不完全。

如果在上面的例子中,基类Person中未定义virtual析构函数,而派生类Student中定义了virtual的析构函数,此时用基类指针指向派生类,再delete掉,运行结果会出错。如果再定义一个类OneSt继承Student,则不会出现错误,因为Student作为基类了。

Effective C++ (第7条:要将多态基类的析构函数声明为虚函数)

需要记住的

应该为多态基类声明虚析构器。一旦一个类包含虚函数,它就应该包含一个虚析构器。

如果一个类不用作基类或者不需具有多态性,便不应该为它声明虚析构器。

基类指针指向派生类的例子,这个很容易考:

参考:http://blog.youkuaiyun.com/dongyanxia1000/article/details/50466729

基类的指针指向派生类的对象,当调用同名的成员函数时:

1)如果在基类中成员函数为虚函数,那么基类指针调用的就是派生类的同名函数。virtual void display();

     可以这么理解:因为该函数是虚的,所以会找真正实现的那个函数,所以调用派生类B中的 B class virtual display.

2)如果基类中成员函数为非虚函数,则调用的是基类的成员函数。void show();

     因为基类是非虚的,已经完全实现了,所以没有必要再调用派生类的了,就调用基类的A class show()

 

8、C++四中cast操作符:

 

参考:http://blog.youkuaiyun.com/starryheavens/article/details/4617637

http://blog.youkuaiyun.com/shun_fzll/article/details/38358195

 

c语言中强制转换符:int a; (float)a;

因为c风格的类型转换有不少的缺点,它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成指向一个派生类对象的指针,这两种转换之间的差别是巨大的,但是传统的c语言风格的类型转换没有区分这些。还有一个缺点就是,c风格的转换不容易查找,他由一个括号加上一个标识符组成,而这样的东西在c++程序里一大堆。所以c++为了克服这些缺点,引进了4种新的类型转换操作符。

对于c++来说,C++标准定义了四个新的转换符:reinterpret_cast, static_cast, dynamic_cast和const_cast,目的在于控制类(class)之间的类型转换。

1、reinterpret_cast

用法:reinpreter_cast<type-id> (expression)

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。

这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。reinpreter_cast是特意用于底层的强制转型,导致实现依赖(就是说,不可移植)的结果。

Int  n=9;

// reinterpret_cast 仅仅是复制 n 的比特位到 d,因此d 包含无用值。

double d=reinterpret_cast<double & > (n);

2、const_cast

用法:const_cast<type_id> (expression)

用于修改类型的const或volatile属性。除了const 或volatile修饰之外,type_id和expression的类型是一样的,一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型,而C不提供消除const的机制(已验证)。

常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

 

3、static_cast

 

最常用的转换,C语言类型的转化,但是转换的时候不会检查类型来保证转换的安全性。

1)用于基本数据类型之间的转换,如把int转换成char,non-const 对象转型为 const 对象(这里相反方向不可以,C++只有const_cast可以)。

2)把空指针转换成目标类型的指针。(之前的做法是用强制转换(type-id*)

3)把任何类型的表达式转换成void类型。

4)应用到类的指针上,它允许子类类型的指针转换为父类类型的指针(upercasting这是一个有效的隐式转换);也能够执行相反动作,即转换父类为它的子类(downcasting),这种转换的安全性需要开发人员来保证(主要是在非上下转型中)。

class Base {};

class Derived : public Base {};

Base *a = new Base;

Derived *b = NULL;

b = static_cast<Derived *>(a); //可以通过编译,但存在安全隐患(如访问//Derived的成员)

 

注意:

1.static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

2.在非基本类型或上下转型中,被转换的父类需要检查是否与目的类型相一致,否则,如果在两个完全不相干的类之间进行转换,将会导致编译出错。

 

4、dynamic_cast

Dynamic_cast 与其他操作符不同,涉及运行类型检验,如果绑定到指针或引用上的对象不是目标类型的对象,则dynamic_cast 失败,如果转换到指针类型的dynamic_cast失败,则结果为0,如果转换到引用类型的dynamic_cast 失败,则抛出bad_cast异常。

因此,dynamic_cast操作符一次执行两个操作,它首先验证被请求的转换是否有效,只有转换有效,操作符才实际进行转换。由于引用或指针在所绑定的对象类型在编译时时未知的,所以dynamic_cast执行的验证只有在运行时进行。

注意:

(1)T必须是类的指针、类的引用或者void *。如果T是类指针类型,那么expression也必须是一个指针,如果T是一个引用,那么expression也必须是一个引用。

(2)dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换(子类->子类/基类)时,dynamic_cast和static_cast的效果是一样的;在进行下行转换(基类->子类)时,dynamic_cast具有类型检查的功能,比static_cast更安全。

(2)dynamic_cast转换符只能用于含有虚函数的类。

也就是说只有基类的指针指向派生类时,这种基类和子类之间的转换才算成功

举例:

class Base { virtual dummy() {} };

class Derived : public Base {};

class Other{} ;

Base* b1 = new Derived;

Base* b2 = new Base;

Derived* d1 = dynamic_cast<Derived *>(b1);  // succeeds

Derived* d2 = dynamic_cast<Derived *>(b2);  // fails: returns 'NULL'

//如果一个引用类型执行了类型转换并且这个转换是不可能的,运行时一个//bad_cast的异常类型会被抛出:

Derived d3 = dynamic_cast<Derived &>(*b1);  // succeeds

Derived d4 = dynamic_cast<Derived &>(*b2);  // fails: exception thrown

注意:Base需要有虚函数,否则会编译出错。

 

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换(子类->子类/基类)时,dynamic_cast和static_cast的效果是一样的;在进行下行转换(基类->子类)时,dynamic_cast具有类型检查的功能,比static_cast更安全。

 

9、智能指针,以及其原理和原因:

 

参考:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html

   智能指针: 智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。

智能指针就是模拟指针动作的类。所有的智能指针都会重载 -> 和 * 操作符。智能指针还有许多其他功能,比较有用的是自动销毁。这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。当然,智能指针还不止这些,还包括复制时可以修改源对象等。智能指针根据需求不同,设计也不同。

智能指针采用计数器的用法:

智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象。

STL常用的4种智能指针类型为:auto_ptr、unique_ptr、shared_ptr和weak_ptr

(1) 为什么现在不用auto_ptr了:为什么现在不用auto_ptr了,因为auto_ptr建立所有权(ownership)概念。对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的构造函数会删除该对象。然后让赋值操作转让所有权。这就是用于auto_ptr和unique_ptr 的策略,但unique_ptr的策略更严格。

(2) 为什么unique_ptr比auto_ptr更严格:

举个例子:auto_ptr<string> p1(new string ("auto") ; //#1

auto_ptr<string> p2;                      //#2

p2 = p1;                                   //#3

对于语句#3,auto_ptr 会执行,p2接管string对象的所有权后,p1的所有权将被剥夺。但如果程序随后试图使用p1,这将是件坏事,因为p1不再指向有效的数据。但是unique_ptr认为#3语句是非法的,所以不再执行语句3避免了p1不再指向有效数据的问题。

(3) 但是对于unique_ptr怎么实现赋值操作呢?

可以采用调用函数的方式返回临时变量的方式进行赋值,如下所示:

unique_ptr<string> demo(const char * s)

{

unique_ptr<string> temp (new string (s));

return temp;

}

unique_ptr<string> ps;

ps = demo('Uniquely special");

demo() 返回一个临时unique_ptr,然后ps接管了原本归返回的unique_ptr所有的对象,而返回时临时的 unique_ptr 被销毁,也就是说没有机会使用 unique_ptr 来访问无效的数据,换句话来说,这种赋值是不会出现任何问题的,即没有理由禁止这种赋值。实际上,编译器确实允许这种赋值,这正是unique_ptr更聪明的地方。

(4) 但是比较常用的还是shared_ptr指针:

  因为shared_ptr的出现就是为了解决所有权转移出现的问题,采用引用计数器的方法,shared_ptr内部用一个计数器来确定对象被引用的次数。引用的时候计数器增加1,当然这个引用计数也是在堆上分配的。确保指向同一个对象的引用计数是同一块内存。取消引用的时候计数器减1计数器减到0的时候就删除这个对象。

 

10、深拷贝和浅拷贝的区别:

答:在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误。

11、关键字static的作用是什么?

C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数,不涉及类;后者主要说明static在类中的作用。

一、面向过程设计中的static
1、静态全局变量:该变量在全局数据区分配内存;未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化);静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的

2、静态局部变量:1)该变量在全局数据区分配内存;
    (2)静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
    (3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
    (4)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

3、静态函数:定义静态函数的好处:
       静态函数不能被其它文件所用;
       其它文件中可以定义相同名字的函数,不会发生冲突;

二、面向对象的static关键字(类中的static关键字)

1、静态成员数据:在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。

2、静态成员函数:与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。普通的成员函数一般都隐含了一个this指针,但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

12、关键字const的作用

在C程序中,const的用法主要有定义常量、修饰函数参数和修饰函数返回值。而在C++程序中,它除了上述功能外,还可以修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改变类中的数据成员。对于定义常量的用法,这里就不多说了,重点看一下修饰函数参数、修饰函数返回值以及修饰函数的定义体。

一、修饰变量或指针

int ii=0; 
const int i=0;           //i是常量,i的值不会被修改 
const int *p1i=&i;        //指针p1i所指内容是常量,可以不初始化 

int const* p11i = &i; //同上,const在*号左边,作用是一样的。
int  * const p2i=ⅈ    //指针p2i是常量,所指内容可修改 
const int * const p3i=&i; //指针p3i是常量,所指内容也是常量 

二、修饰函数参数

    首先如果该参数用于输出,那么无论是采用指针传递还是引用传递,都不能加const修饰。所以const只能用于修饰输入参数。这里又分三种情况:输入参数采用值传递还是指针传递还是引用传递。

(1)如果采用值传递,

由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不需要加const 修饰。例如,对于函数void Func1(int x),写成void Func1(const int x)一点意义也没有。同理,对于void Func2(A a)也不需要写成void Func2(const A a),其中A为用户自定义的对象类型。

(2)如果采用指针传递,那么加const可以防止函数体内部对该参数进行改变,起到保护作用。

例如,假设StringCopy函数定义为:void StringCopy(char *strDest, const char *strSrc),那么,如果函数体试图改变strSrc的内容,编译器将报错。    

(3)如果采用引用传递

     首先我们来说一下,为什么要引入引用传递这种方法。原因是:对于非内部数据类型的参数而言,像void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为void Func(A& a)。这样一来,根据引用传递的定义,只是借用了参数的别名,不需要产生临时对象。

三、修饰函数的定义体。

       定义const函数,只需要将const关键字放在函数声明的尾部。任何不会修改类的数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将报错,这无疑会提高程序的健壮性

13、 简述C,C++程序编译的内存分配情况?

解:C,C++中内存分配方式可以分为三种:

1. 从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快,不容易出错,因有系统自行管理。

2. 在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

3. 从堆上分配:即运态内存分配。程序在运行时候用malloc或new申请任意大小的内存,程序员自己负责在何进用free 和delete释放内存。

一个C、C++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区和程序代码区。

 

14、初始化列表c++:

除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表

· 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面

· 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面

· 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。

 

 

15.new malloc 的区别,问的比较深

 

1、本质区别:new /delete是c++中的操作符,malloc/free 是 C/C++语言的标准库函数

2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数

3、用法上不同:

用malloc 申请一块长度为length 的整数类型的内存,程序如下:

int *p = (int *) malloc(sizeof(int) * length);

对于malloc 主要的两点是:“类型转换”和“sizeof”

而malloc返回的都是void指针,所以需要强制转换

malloc 函数返回的是 void * 类型。对于C++,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:”不能将 void* 赋值给 int * 类型变量”。所以必须通过 (int *) 来将强制转换。而对于C,没有这个要求,但为了使C程序更方便的移植到C++中来,建议养成强制转换的习惯。

int* p;

p = (int *) malloc (sizeof(int)*128);

//分配128个(可根据实际需要替换该数值)整型存储单元,

//并将这128个连续的整型存储单元的首地址存储到指针变量p中

 

而对于new比较简单,直接可以 Obj *objects = new Obj[100];     这是因为new 内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new 在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new 的语句也可以有多种形式。


3、内存泄漏对于malloc或者new都可以检查出来的,区别在于new可以指明是那个文件的那一行,而malloc没有这些信息。(new可以说出错误的具体问题,而malloc不能)
4、new 和 malloc效率比较
   new可以认为是malloc加构造函数的执行。
   new出来的指针是直接带类型信息的。

Malloc申请空间的原理讲的比较清晰

malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。

16、_stdcall,_cdecl区别

(1) _stdcall调用

    _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题:

#define WINAPI _stdcall

  按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数。

(2) _cdecl调用

_cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。_cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。 

17、实现strcpy公式:

(1) char  * strcpy ( char  * strDest ,  const   char  * strSrc )

{

     assert (( strDest != NULL ) && ( strSrc  != NULL ));//这个必须要啊,判断指针是否为空

     char  * address  =  strDest ;                                        

     while ( (* strDest ++ = *  strSrc ++) !=  '\0'  )         

               NULL  ;

     return   address  ;                                                

}

( 2 ) strcpy 能把 strSrc 的内容复制到 strDest ,为什么还要 char *  类型的返回值?

答:为了 实现链式表达 式。  

18、文件声明的区别

#include<filename.h>系统检索头文件时,会先从系统文件里开始找,再找其他地方,用于系统文件较快。

#include “filename.h”系统检索文件时,先从程序所处目录开始查找,用于自定义文件比较快。

ifndef/define/endif 的含义:如果未定义 / 那么定义 / 完成假设。一般是用来防止头文件被重复包含,提高编译效率的。

 

19、map是用什么实现的,插入数据的方式有哪几种,有什么不同

 

C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般的平衡二叉树,所以在存储map时是默认有序的。

在map和set中查找是使用二分查找,所以时间复杂度为Olog(n)

插入数据的模式有三种:

(1)   my_Map.insert(map<string,   int>::value_type("b",2)); 
(2)   my_Map.insert(make_pair<string,int>("d",4))

(3)   my_Map["a"]   =   1;  //我经常用插入数据的方法,居然忘了

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值.

那怎么判断是否插入成功了呢?

mapStudent.insert(map<int, string>::value_type (1, "student_one"));

 mapStudent.insert(map<int, string>::value_type (1, "student_two"));

 

上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下

 pair<map<int, string>::iterator, bool> Insert_Pair;

 Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, "student_one"));

 

我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。

 

20、lower_bound 和upper_bound 函数的用法

 

ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。

ForwardIter upper_bound(ForwardIter first, ForwardIter last, const _Tp& val)算法返回一个非递减序列[first, last)中第一个大于val的位置。

 

 

 

 

vivo图像算法校招笔试解析:从数学基础到工程实现 图像算法工程师的面试考察,往往不限于深度学习模型的堆砌,而是更看重数学功底、经典图像处理原理与工程落地能力。矩阵特征值分解与SVD在图像压缩中的应用、贝叶斯公式在缺陷检测中的基率谬误、直方图均衡化的手算归并、高斯滤波的频域优势、拉普拉斯算子的锐化陷阱,这些都是笔试中高频出现的核心考点。掌握这些基础概念,不仅有助于理解图像去噪、增强、分割等经典算法的技术价值,也能在手机拍照、文档扫描等实际工程场景中灵活运用。本文围绕vivo 2019校招笔试题,系统梳理了数学基础、图像处理经典算法、机器学习与编程题的考查重点 阅读详情

相关推荐

isp图像算法工程师的大厂面试题2023

这里列出了一些可能出现在ISP(图像信号处理)图像算法工程师大厂面试中的问题。这些问题涵盖了图像处理、计算机视觉、编程和算法等多个方面。请注意,这些问题的复杂程度因公司和职位而异,应根据特定的面试情况进行准备。

qq_39735798的博客 1330

图像处理职位面试题汇总(1)

Matlab 中读、写及显示一幅图像的命令各是什么?解:第一、Matlab中读图像函数是imread( )。imread 函数用于读入各种图像文件,其一般的用法为:[X,MAP]=imread(‘filename’,‘fmt’)其中,X,MAP分别为读出的图像数据和颜色表数据,fmt为图像的格式,filename为读取的图像文件(可以加上文件的路径)。Intel指令集中MMX,SSE,SSE2,SSE3和SSE4指的是什么?解:Intel指令集中MMX(Multi Media eXtension,多媒体扩展

松子茶的专栏 2万+

vivo 2019校招图像算法工程师笔试题解析:核心考点与拉普拉斯锐化实战

图像处理作为计算机视觉与终端成像系统的核心技术,在智能手机影像优化中扮演着关键角色。理解卷积运算与边缘检测算子的原理,是掌握图像增强与锐化算法的基础。拉普拉斯算子作为一种二阶微分算子,通过检测灰度突变实现边缘提取,将其与原始图像叠加即可完成图像锐化,这一技术在相机ISP链路中有着广泛应用。针对终端厂商的算法岗位笔试,经典图像处理算法的工程实现能力往往比深度学习模型更为重要。本文围绕vivo 2019校招图像算法工程师笔试题,系统梳理题型逻辑、核心考点与代码实现要点,重点剖析拉普拉斯锐化的数学推导、边界处理与

weixin_30673611的博客 452

面试题

一、图像处理题目 注意,一下所有需要写代码的题目,不允许使用OpenCV的Mat类。如果图片内容需要用指针读取。 1. 给定0-1矩阵,求连通域。(遇到过N次,笔试面试都有,最好做到能徒手hack代码或者伪代码。) 2. 写一个函数,求灰度图的直方图。 3. 写一个均值滤波(中值滤波)。 4. 写出高斯算子,Sobel算子,拉普拉斯算子等,以及它们梯度方向上的区别。 5

danteLiujie的专栏 1350

小米面试——计算机视觉算法实习生

13.虚函数表(原来就是虚表,卤煮答 没听过啊,这里面试官笑了,说“没听过不要紧,我们换下一道”)面完百度了一下,主要就是 动态绑定,继承类调用基类虚函数,指针数组,虚函数的指针什么的。6.买卖股票的合适时间-入门I级(记录最小值和最大值,卤煮舍友昨日头条原题,真香!卤煮表示,简历写的是 C++使用经验,并不精通, 看不懂啊啊啊!5. 求取单链表的中间值(①遍历求表长,取n/2②快慢指针)7.字符串最长不重复子串( 哈希表,思路和 买卖股票一样)16.进程与线程,线程共享的资源( 堆,全局变量)

FPGA/MATLAB学习教程/源码/项目合作开发 2018

C++程序员简历02.doc背后:从面试考点到工程实战

C++是一门横跨底层原理与工程实践的编程语言,既要求开发者理解内存布局、编译链接等底层机制,也要求熟练运用STL、智能指针与多线程等现代特性,这正是C++开发岗位面试中高频考察的能力图谱。从技术价值看,掌握这些知识点不仅是应对笔试和手撕代码的基础,更是构建高性能、高并发系统的关键能力。在实际应用中,无论是后端服务、音视频处理,还是OpenCV图像算法工程化,都依赖这份扎实的语言功底。而一份规范的C++简历,恰恰是这些能力的浓缩呈现。围绕简历背后真正被面试官反复审视的内容,梳理从语言基础、多线程并发、STL原

weixin_29206669的博客 300

计算机视觉面试c++

前天测试了两场 上午c++视觉 下午游戏公司 细节: 一、写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值。 int a = 4; (A)a += (a++); (B) a += (++a) ;© (a++) += a;(D) (++a) += (a++); a = ? 答: (A)9 (B)10 ©错误 (D)错误 二、请填写BOOL , float, 指针变量...

weixin_43358624的博客 2297

深入理解C语言内存管理:堆与栈的区别

栈是一种遵循后进先出(LIFO)原则的数据结构。在程序中,栈用于存储局部变量、函数的参数以及函数调用时的返回地址等信息。栈的内存管理由操作系统自动进行,每次函数调用时都会在栈上分配一块内存区域,函数执行完毕后,该内存区域会自动释放。在C语言中,堆与栈是两种不同的内存分配方式,各自有着不同的特点和适用场景。栈内存自动管理,访问速度快,但大小有限,适用于存储局部变量和函数调用信息。堆内存由程序员手动管理,适用于存储动态数据结构,大小不受限制,但访问速度较慢,容易导致内存泄漏等问题。

set_one的博客 1579

C++工程师面试题(是否都会)

C++工程师面试题,C、C++、数据库、数据结构、网络、操作系统知识点

bigger_belief的博客 1342

从流量到凭证:实战解析SMB协议中的NTLMv2/v1哈希提取与破解

本文详细解析了SMB协议中NTLMv2/v1哈希的提取与破解实战技巧。从流量捕获、哈希格式处理到Hashcat高效破解,提供了一套完整的操作指南。文章特别强调了NTLMv2和NTLMv1哈希的区别及处理要点,并分享了防护建议与检测方法,帮助安全人员提升渗透测试效率。

weixin_30642561的博客 116

电流镜结构实战:从零理解MOS管偏置电路设计(附吴金课程补充)

本文深入解析电流镜结构在MOS管偏置电路设计中的关键作用,从基本原理到实战应用全面覆盖。通过分析偏置电路的核心原理、破解设计难题的实用技巧,以及进阶优化策略,帮助工程师掌握这一模拟电路设计的核心技术。特别适合需要理解电流镜结构和基准电路设计的读者参考学习。

ujm5678901的博客 256

图像算法工程师(AI算法工程师)的面试问题

面试官可能会根据你的简历经历和对问题的回答深入探讨特定领域,所以建议在面试前充分复习相关知识点,并准备好具体的项目案例来展示你的实际经验和解决问题的能力。

小宝哥Code的专栏 1354

企业AI数据资产评估的自动化工具:AI应用架构师的使用指南

在AI驱动的企业数字化转型中,数据资产是支撑模型训练、业务决策的核心燃料。然而,80%的AI项目失败源于数据问题——低质量数据导致模型偏差、未评估的风险引发合规危机、价值不明确的数据浪费资源。手动数据资产评估效率低、易出错,无法满足规模化AI应用需求。本文将以AI应用架构师的视角,拆解企业数据资产评估的核心逻辑,用"餐厅选食材"的生活化比喻解释复杂概念,结合自动化工具的技术原理与实战案例,教你如何从0到1搭建数据资产评估体系。无论是数据质量检测、价值量化还是风险防控,你都能找到可落地的工具方案与实践步骤。

2502_91592937的博客 1629

推荐收藏!这是我见过计算机视觉图像算法最全面经了

今年CV方向算法工程师非常难找,投递CV算法的毕业生越来越多,各个CV岗位(包括研究岗与业务线上的算法工程师岗)对于求职人员的要求也越来越高。本文以自己春招实习以及秋招的经历为基础,整理秋招求职的视觉图像算法中的经常会遇到的一些面试问题。主要整理一些常问的基础知识以及算法知识。由于每个人自己的项目不同,岗位的不同问题也会有一些不同,这些基础问题应该是都有所理解的,这些基础知识作为查漏补缺来看吧。

机器学习社区 2868

New API 大模型网关保姆级教程:Docker Compose 部署 + MiniMax 接入 Claude 实战

New API 是一个开源的 AI 基座平台,提供统一的 API 接口接入 30+主流 AI 服务(如 OpenAI、Claude 等)。核心功能包括智能路由、精细计费、安全管控和多租户支持,采用 AGPLv3 协议开源。支持 Docker Compose 快速部署,通过修改配置文件即可连接不同数据库,适合从开发到生产环境的不同规模应用。部署时需注意修改默认密码等安全配置。

甘蓝的专栏 1602

YOLOv8集成CPCA(Combined Parallel Convolutional Attention)注意力机制模块YOLOv8深度教程

YOLOv8集成CPCA注意力模块教程摘要 本教程详细介绍了如何将YOLOv8 CPCA(Combined Parallel Convolutional Attention)注意力模块集成到YOLOv8目标检测框架中。CPCA模块结合了通道注意力和多尺度空间注意力机制,通过全局池化和双路径融合增强通道特征,并利用多尺度深度可分离卷积捕获空间上下文信息。YOLOv8 教程包含完整的实现步骤:创建CPCA模块代码、修改YOLOv8模型解析逻辑、编写自定义配置文件,YOLOv8YOLOv8YOLOv8YOLOv8

FJN110的博客 1619

图像算法工程师——面试经验

TCL研究员面试(凉凉)      在接到面试通知后匆忙准备一下面试知识后(由于之前就秋招已经准备了很长时间),就前往了研发中心,HR小姐姐先是简单的了解一下情况之后把我的简历和相关资料交给了技术主管,技术主管看了简历之后开始逐条的询问,主要类容回忆如下: 1.为什么要用数字信号处理 2.询问了有关项目的问题,对比度是怎么能够实现自适应的调整,在匹配图像时是怎么实现快速匹配的,如何匹配的,对...

feiyanjia的博客 1万+

如何借助Gemini 3 Pro完成一篇文献精读?(劝收藏)

金句必须是原文的完整句子,并附上该句子在文中的大致位置。你是一名资深科研文献评估专家,请根据我提供的文献信息(标题、作者、期刊、时间、引用、摘要、结论、图表)依次输出:①影响力评估:按期刊、作者、时间、引用、问题重要性给出1–10分及简述;用上述方法再结合Gemini 3 Pro的辅助,原本需要3小时才能读完一篇文献,现在只需50分钟,不管是顶刊论文还是领域内冷门论文,都可以用这套方法,另外七哥设计的高阶精读提示词,需根据自己的文献内容做调整,希望这篇文章的方法能帮你高效精读文献,掌握文献的精华内容。

智能AI让学术科研更容易 1301

面试复盘-AI图像算法-日常实习

AI图像算法岗面试复盘

Dead_John 742

[VCS]VCS checkpoint简介以及其在SoC验证加速中的作用

VCS checkpoint是Synopsys VCS提供的快照/恢复机制,可显著加速SoC验证。其核心是在仿真关键节点(如完成初始化后)保存系统状态,后续测试可直接从该点恢复,避免重复执行冗长的初始化阶段(如boot、DDR训练等)。该技术特别适用于多测试用例共享同一初始状态的场景,通过分离初始化与功能验证流程,可提升回归效率3-5倍。需注意处理DPI-C状态同步、版本管理及存储优化等问题,结合UVM和自动化脚本可实现更高效的验证流程。典型应用可节省数百万cycle的重复仿真时间。

元直的博客 774

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

20170816——Yi+图像算法实习生

重拾勇气重振旗鼓的陈子平同学再一次踏上了投简历面试被虐之路。 意料之中的铩羽而归。 8.15早上投的简历,下午接到通知,8.16下午3点的电话面试,Yi+的图像算法实习生。   工作职责:  1.具有图像处理、计算机视觉,模式识别,视频分析等方面的理论知识和研究背景,能熟练阅读相关英文论文和专利;  2.良好的C/C++/CUDA程序开发能力和算法实现功底、 熟悉OpenCV、Pyth

cheng_zipi的博客 1397

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

字节跳动算法工程师面试总结,android综合面试

自我介绍一下,小编13年北京科技大学毕业,曾经在字节跳动待过,也去过vivo、小米等大厂,18年进入华为一直到现在。小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担,能在岗位上再创辉煌,步步高升!!。

2401_84901122的博客 460

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

安卓工程面试问题,2024阿里手淘Android面试题目

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!这里附上我整理的几十套腾讯、字节跳动,京东,小米,头条、阿里、美团等公司19年的Android面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。由于篇幅有限,这里以图片的形式给大家展示一小部分。

2401_83329718的博客 834

pyqt结合深度学习框架做系统

图像算法,以及视觉算法,就靠大家平时积累了,传统算法要会(opencv库),深度学习框架也要会,语言python是必须的,所有包括软件测试也要会语言,c也行,c++。(吃土也不忘学习,将pyqt和之前的深度学习训练的识别模型结合起来,实现了界面化,可以当作系统了) 实现了登录、注册、主页。三个页面的灵活切换,其中主页面如下图,实现了上传原图的功能和病害识别的功能

m0_63172128的博客 1973

硕士毕业,两年北漂算法工程打工生活【上】

这篇【硕士毕业20-22的两年北漂打工生活】博文内容半年之前就打了草稿了,一直没有很好的语言逻辑来组织,今日稍加润色,各位读者大大姑且一看,仅供娱乐,不供参考本文所述,基础信息如下,特征带入,只对本博文内容有效,不保证真实性2020年6月初 至 2022年 5月底北京211硕士软件工程95男回龙观图像算法哦,下面这个看起来有点呆的才是博主墨理啦上面那是我女朋友认真学习的样子,太好看了吧。

专注于AI领域前沿技术学习与分享:目标检测、图像修复、超分重建、AI工程化 1819

大恒图像面经(算法研发工程…

原文地址:大恒图像面经(算法研发工程师)作者:yigerenjiandan 2012年8月30日下午3:00来到大恒图像公司,公司职员给了一份笔试,紧接着就是面试。其中最搞笑的是我正在做笔试题,他们居然在单位里做第八套广播体操,不过还是要赞一个的,感觉挺不错的。下面就跟大家分享一下大恒图像的笔试题。我面的是算法工程师,笔试题都是很基本的题,可是我答的很烂,主要是因为准备补充分吧 1、C语言题,主

wangxiaofei558的博客 5314
上一篇: 招工作的辛苦历程—国企事业单位篇
下一篇: 判断点是否在三角形内 和 点是否在矩形内
Traveling_DING
博客等级 码龄12年 65粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值