一些C ++特定的面试问题 [英] some C++-specific interview questions

查看:65
本文介绍了一些C ++特定的面试问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是世界上最伟大的C ++程序员,所以我有一个很难的时间。一些帮助将不胜感激。


1.评论下面的功能声明Bar():

class Foo

{

static int Bar(int i)const;

}


(我说因为Bar是静态方法,所以只能访问
静态变量,而不是成员变量,所以const是

无关紧要。)

2.如果你有虚拟函数上课,你需要一个虚拟的

析构函数吗?为什么?


(我的直觉回答是,不,你不需要虚拟析构函数

,除非派生类处理它自己的动态管理

数据。)


3.评论以下功能。你会改变什么?状态

您的假设:


string& Foo()

{

string default_string =" default answer" ;;

for(vector< node> :: iterator iter = mynodes。 begin();

iter!= mynodes.end();

iter ++)

{

cout< ;< iter;

}

返回default_string;

}

4.你什么时候使用私有继承? (我从来没有亲自

使用过这个。)


5.内存中的虚拟函数查找表存储在哪里?

(我发现这个对我来说太详细了。)


6.考虑成员初始化列表。他们为什么需要?为什么

他们认为比构建者

中的成员更有效率?

I''m not the world''s greatest C++ programmer, so I had a hard
time with these. Some help would be appreciated.

1. Comment on the declaration of function Bar() below:
class Foo
{
static int Bar(int i) const;
}

(I said that since Bar is a static method, it can only access
static variables, not member variables, so the const is
irrelevant.)
2. If you have virtual functions in your class, do you need a virtual
destructor? Why?

(My gut answer was that no, you don''t NEED a virtual destructor
unless the derived class is handling its own dynamically-managed
data.)

3. Comment on the following function. What would you change? State
your assumptions:

string & Foo()
{
string default_string = "default answer";
for (vector<node>::iterator iter = mynodes.begin();
iter != mynodes.end();
iter++)
{
cout << iter;
}
return default_string;
}
4. When would you use private inheritence? (I have never personally
used this.)

5. Where in memory is the virtual function lookup table stored?
(I found this one to be way too detailed for me.)

6. Consider member initialisation lists. Why are they needed? Why are
they considered more efficient than initialising members in the body of
the constructor?

推荐答案

Digital Puer写道:
Digital Puer wrote:

我不是世界上最伟大的C ++程序员,所以我有一个很难的

这些时间。一些帮助将不胜感激。
I''m not the world''s greatest C++ programmer, so I had a hard
time with these. Some help would be appreciated.



下一个问题是你的面试官可能不是世界上最伟大的,

要么...; - )

The next problem is your interviewer might not be the world''s greatest,
either... ;-)


1.评论下面的功能声明Bar():

class Foo

{

static int Bar(int i)const;

}


(我说因为Bar是静态方法,所以它只能访问

静态变量,而不是成员变量,所以const是

无关。)
1. Comment on the declaration of function Bar() below:
class Foo
{
static int Bar(int i) const;
}

(I said that since Bar is a static method, it can only access
static variables, not member variables, so the const is
irrelevant.)



我怀疑它不应该是偶数编译。

I suspect it should not even compile.


2.如果你的班级有虚拟功能,你需要一个虚拟的

析构函数吗?为什么?
2. If you have virtual functions in your class, do you need a virtual
destructor? Why?


(我的直觉回答是不,你不需要虚拟析构函数

除非派生类是处理自己动态管理的

数据。)
(My gut answer was that no, you don''t NEED a virtual destructor
unless the derived class is handling its own dynamically-managed
data.)



在这种情况下,你必须回答两次;最安全的方式和技术上正确的方式。最安全的方法是所有析构函数都是虚拟的,除非分析

显示需要删除虚拟。那是安全的,因为队友可能会写一个继承你班级的班级,然后写一个''删除'',它使用

a指针指向你的班级,不是派生类。删除这样一个对象,没有虚拟析构函数的
是未定义的行为。


技术答案是否定的,你永远不需要做一个析构函数

虚拟,如果你知道没有人会通过指向

基类的指针删除它。


和其他虚拟方法只是间接表示。他们不会影响技术或语义决策,使析构函数变得虚拟。

间接地,从语义上讲,你不应该从没有继承的类继承

虚拟方法,因此你永远不应该删除指向其基类的指针。


至少问题不是如果析构函数没有释放资源,那么必须

是虚拟的?这意味着删除指向

基类的指针的常见谬误只会在创建泄漏时创建未定义的行为。

未定义的行为实际上是在析构函数时间开始的,无论是什么然后

泄漏。

In this case, you must answer twice; both the safest way and the technically
correct way. The safest way is "all destructors are virtual unless profiling
reveals the need to remove a virtual". That''s safe, because a teammate might
write a class that inherits your class, and then write a ''delete'' that uses
a pointer to your class, not the derived class. Deleting such an object,
without a virtual destructor, is undefined behavior.

The technical answer is no, you never are required to make a destructor
virtual, if you know that nobody will ever delete it through a pointer to
the base class.

And the other virtual methods are only indirectly indicated. They don''t
influence the technical or semantic decision to make the destructor virtual.
Indirectly, semantically, you should not inherit from a class with no
virtual methods, hence you should never delete a pointer to its base class.

At least the question wasn''t "If a destructor releases no resources, must it
be virtual?" That implies the common fallacy that deleting a pointer to the
base class will only create undefined behavior if it creates a leak. The
undefined behavior actually starts at destructor time, regardless what then
leaks.


3.评论以下功能。你会改变什么?状态

您的假设:


string& Foo()

{

string default_string =" default answer" ;;

for(vector< node> :: iterator iter = mynodes。 begin();

iter!= mynodes.end();

iter ++)

{

cout< ;< iter;

}

返回default_string;

}
3. Comment on the following function. What would you change? State
your assumptions:

string & Foo()
{
string default_string = "default answer";
for (vector<node>::iterator iter = mynodes.begin();
iter != mynodes.end();
iter++)
{
cout << iter;
}
return default_string;
}



它返回一个引用一个被破坏的本地,所以'未定义。


接下来,vector< nodeis not typedeffed。


接下来,default_string有与for循环无关,可能只是一个诱饵。
只是一个诱饵。无论如何,你应该宣布这个函数有两个独立的东西,应该分成两个。


接下来,cout<< iter的定义很差,无法生成无用的东西,可能是指针地址。如果运算符<<为''node''定义,然后cout<< * iter

可能更有用。


接下来,所有迭代器应始终称为''it''。 ;-)

It returns a reference to a destructed local, so that''s undefined.

Next, vector<nodeis not typedeffed.

Next, the default_string has nothing to do with the for-loop, which could be
just a decoy. Regardless, you should announce the function does two
independent things and should be split in two.

Next, cout << iter is poorly defined to produce something useless, possibly
a pointer address. If operator<< is defined for ''node'', then cout << * iter
might be more useful.

Next, all iterators should always be called ''it''. ;-)


4.你什么时候使用私人继承? (我从来没有亲自

使用过这个。)
4. When would you use private inheritence? (I have never personally
used this.)



Per / C ++编码标准/ Sutter和Alex A.,你应该更喜欢它

公共继承。


考虑抽象模板模式,但只有派生类

知道他们称之为秘密父母然后,反过来,调用他们专门的

方法来帮助它执行模板化操作。


(警告:这不是C ++模板。 ..)

Per /C++ Coding Standards/ by Sutter and Alex A., you should prefer it to
public inheritance.

Consider the Abstract Template Pattern, but where only the derived classes
know they call a secret parent that then, in turn, calls their specialized
methods to help it perform their templated action.

(Warning: That''s not a C++ template...)


5.内存中的虚拟函数查找表存储在哪里?

(我觉得这个太详细了对我来说。)
5. Where in memory is the virtual function lookup table stored?
(I found this one to be way too detailed for me.)



我不知道这个答案是标准的,但它存储在已初始化的全球

全球数据段。除了在最恶劣的调试情况下,这个事实(即使是它的准确版本)也不应该在实践中使用。

I don''t know how Standard this answer is, but it''s stored in the initialized
global data segment. This fact (even its accurate version) should never be
used in practice, except in the sickest debugging situations.


6.考虑成员初始化列表。他们为什么需要?
6. Consider member initialisation lists. Why are they needed?



因为他们明确地向你的同事和

编译器声明了意图。

Because they explicitly declare intent, to both your colleagues and to the
compiler.


为什么

他们认为比构造函数初始化成员更有效率?
构造函数?
Why are
they considered more efficient than initialising members in the body of
the constructor?



因为编译器可以生成最有效的代码来实现它们。

它们的定义与成员出现的顺序相同在

类的定义中,所以编译器可以像展开的

循环一样高效地将它们全部插入。


此外,如果你把它们写成乱序,有些系统会发出警告。

这有助于你的代码自我纠正。


接下来,你的构造函数的主体应该是异常中立且安全的。所以

将指针(NULL)放在成员列表中,然后在

正文中指针= new,如果构造函数可以导致更安全的''删除''然后吹。 (但是

析构函数不会调用,所以仍然喜欢智能指针!)


接下来,如果任何成员的初始化抛出异常,堆栈退绕

将以相反的顺序调用每个完全构造的成员的析构函数。


一般来说,效率是一个糟糕的任务主管。过早优化是所有邪恶的根源。在这种情况下,如果

结果也是_cognitively_有效的话,你可能会在效率方面犯错误。在您训练将它们识别为重要部分后,会员初始化列表更容易理解。

的构造函数。因此,请遵循以下规则:永远不要进入任何未初始化状态的成员的开头{

构造函数。


只需使用,您就可以轻松获得该规则智能数据成员,例如smart

指针和其他包含默认构造函数的对象。


-

Phlip http://c2.com/cgi/wiki?ZeekLand < - 不是博客!!!

Because the compiler can generate the most efficient code to implement them.
They are defined to occur in the same order as the members appear in the
class''s definition, so the compiler could get as efficient as an unrolled
loop to stomp them all in.

Further, some systems can provide a warning if you write them out of order.
This helps your code self-correct.

Next, your constructor''s body should be exception neutral and safe. So
putting pointer(NULL) in the member list, and then a pointer=new in the
body, can lead to a safer ''delete'' if the constructor then blows. (But the
destructor won''t call, so still prefer smart pointers!)

Next, if any member''s initialization throws an exception, the stack unwinder
will call the destructor of each fully constructed member, in reverse order.

In general, efficiency is a poor taskmaster. Premature optimization is the
root of all evil. In this case, you may err on the side of efficiency if the
result is also _cognitively_ efficient. Member initialization lists are
easier to comprehend, after you train to recognize them as important parts
of constructors. So follow this rule: Never enter the opening { of a
constructor with any member in an uninitialized state.

You can get that rule easily by only using smart data members, such as smart
pointers and other contained objects with default constructors.

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!




Digital Puer写道:

Digital Puer wrote:

1.评论下面的功能声明Bar():

class Foo

{

static int Bar(int i)const;

}


(我说过,因为Bar是静态方法,它只能访问
静态变量,而不是成员变量,所以const是

无关紧要。)
1. Comment on the declaration of function Bar() below:
class Foo
{
static int Bar(int i) const;
}

(I said that since Bar is a static method, it can only access
static variables, not member variables, so the const is
irrelevant.)



我认为你是对的。 const是无关紧要的。

I think you are right. const is irrelavant.


2.如果你的课程中有虚函数,你需要一个虚拟的

析构函数吗?为什么?


(我的直觉回答是,不,你不需要虚拟析构函数

,除非派生类处理它自己的动态管理

数据。)
2. If you have virtual functions in your class, do you need a virtual
destructor? Why?

(My gut answer was that no, you don''t NEED a virtual destructor
unless the derived class is handling its own dynamically-managed
data.)



基类的私有数据成员怎么样?在任何情况下,它们都不是继承的b $ b。那么如何删除它们呢?我认为我们需要在两个班级的




我无法理解第三个。

What about the private data members of base class? They are not
inherited in any case. So how to delete them? I think we need that in
both classes.

I can''t understand the third one.


4.你什么时候使用私人继承权? (我从来没有亲自

使用过这个。)
4. When would you use private inheritence? (I have never personally
used this.)



我也是。但它用于使所有公共和受保护的基础

类成员成为派生类中的私有成员。 (我想你已经知道了

这个)

me too. but it is used to make all public and protected members of base
class as private members in derived class. (I think you already know
this)


5.内存中的虚拟函数查找表存储在哪里?

(我发现这个对我来说太详细了。)
5. Where in memory is the virtual function lookup table stored?
(I found this one to be way too detailed for me.)



V表指针通常存储在

基类。这意味着它是堆。当你看到班级大小时,

班级大小将包含成员变量大小和(没有虚拟

函数*指针大小)

The V-table pointer is generally stored just after the elements of the
base class. That means it is heap. When you see the class size, the
class size will contain member variables size and (no of virtual
functions * pointer size)


6.考虑成员初始化列表。他们为什么需要?为什么

他们认为比在构造函数中初始化成员更有效率?
6. Consider member initialisation lists. Why are they needed? Why are
they considered more efficient than initialising members in the body of
the constructor?



我只是猜测第6个问题。

为什么需要它们?

它们通常被使用初始化const成员变量(也不是
const)。

为什么它们更有效率?

真的不知道。但通常当你在身体上书写时,你会明智地写出
。但是在这里你使用逗号运算符编写并通过大括号分配

。这会带来任何表现吗?请告诉我。


- Murali Krishna

I am just guessing on the 6th Question.
Why are they needed?
They are generally used to initialize const member variables (also non
const).
why are they more efficient?
really don''t know. but normally when you write in the body, you write
statement wise. but here you write using comma operator and assign
through braces. So does this bring any performance? please let me know.

-- Murali Krishna


Digital Puer写道:
Digital Puer wrote:

我不是世界上最伟大的C ++程序员,因此我有一个很难的时间。一些帮助将不胜感激。


1.评论下面的功能声明Bar():

class Foo

{

static int Bar(int i)const;

}


(我说因为Bar是静态方法,所以只能访问

静态变量,而不是成员变量,所以const是

无关紧要。)
I''m not the world''s greatest C++ programmer, so I had a hard
time with these. Some help would be appreciated.

1. Comment on the declaration of function Bar() below:
class Foo
{
static int Bar(int i) const;
}

(I said that since Bar is a static method, it can only access
static variables, not member variables, so the const is
irrelevant.)



I认为它没有编译,因为const不允许静态

函数

I think it doesn''t compile because const is not permitted with static
functions


>

2如果你班上有虚拟功能,你需要一个虚拟的

析构函数吗?为什么?


(我的直觉回答是,不,你不需要虚拟析构函数

,除非派生类处理它自己的动态管理

数据。)
>
2. If you have virtual functions in your class, do you need a virtual
destructor? Why?

(My gut answer was that no, you don''t NEED a virtual destructor
unless the derived class is handling its own dynamically-managed
data.)





删除指针时需要虚拟析构函数来调用apropiate析构函数-基础。堆内存是一个原因,但一般来说,当派生类的析构函数有事可做时,是必要的。


一般来说,当你有虚函数使析构函数虚拟化。

Virtual destructor is needed for calling the apropiate destructor when
delete a pointer-to-base. Heap memory is one reason, but in general, is
necessary when derived class''s destructor has something to do.

In general, when yo have virtual functions make destructor virtual.


3.评论以下函数。你会改变什么?状态

您的假设:


string& Foo()

{

string default_string =" default answer" ;;

for(vector< node> :: iterator iter = mynodes。 begin();

iter!= mynodes.end();

iter ++)

{

cout< ;< iter;

}

返回default_string;

}
3. Comment on the following function. What would you change? State
your assumptions:

string & Foo()
{
string default_string = "default answer";
for (vector<node>::iterator iter = mynodes.begin();
iter != mynodes.end();
iter++)
{
cout << iter;
}
return default_string;
}



你要回来了对函数的本地数据的引用。因为它是本地的,所以当函数完成时它将被销毁。

通常当你在一个函数内部构造一个constact值时你就会生成

变量static。使用静态变量,您可以通过

引用返回值,但是我将返回类型为const,用于对其值进行fobidding修改。

Iterator就像一个指针,因此你必须对它进行反驳:

cout<< * iter;

You are returning a reference to local data of your function. As it''s
local it will be destroyed when function is finished.
Usually when you construct a constact value inside a function you make
the variable static. With static variable you can return value by
reference, but I''d make return type const, for fobidding modification on
its value.

Iterator acts like a pointer, thus you must derrefence it:
cout << *iter;


4.你什么时候使用私人继承权? (我从来没有亲自

使用过这个。)
4. When would you use private inheritence? (I have never personally
used this.)



当继承用于重用实现但是不是 - 一个

关系。私有继承隐式指向基础

转换是不允许的。

When inheritance is for reusing implementation but hasn''t a is-a
relationship. With private inheritance implicit pointer-to-base
conversion is not permitted.


>

5。内存中的虚拟函数查找表存储在哪里?
(我觉得这个对我来说太详细了。)
>
5. Where in memory is the virtual function lookup table stored?
(I found this one to be way too detailed for me.)



I认为vtable细节不包含在C ++标准中(我不确定,

但我认为)。

通常编译器构造它(我不知道) where),指针和

引用都有一个链接对它来说。

我不确定这个问题,因为我不记得我过去曾读过的关于它的内容。我建议你阅读Stanley B. Lippman的'Inside

C ++对象模型'。

I think vtable details are not covered in C++ standard (I''m not sure,
but I think it).
Usually compilers construct it (I don''t know where), and pointers and
references have a "link" to it.
I''m not sure on this question, because I don''t remember well what I read
about it in the past. I suggest you to read Stanley B. Lippman''s "Inside
the C++ object model".


6.考虑成员初始化名单。他们为什么需要?为什么

他们认为比在构造函数中初始化成员更有效率?
6. Consider member initialisation lists. Why are they needed? Why are
they considered more efficient than initialising members in the body of
the constructor?



初始化基础clases的非默认构造函数需要它们。

当你不初始化初始化列表中的成员时,它是默认初始化的
,因此当你在一个

构造函数体内初始化它时,它初始化了两次。

当你初始化初始化列表中的一个成员,即

唯一的inisialization。

They are needed for initializating not-default constructor of base clases.
When you don''t initialise a member in an initialisation list, it is
initialised by default, thus when you initialise it inside the body of a
constructor it''s initialised twice.
When you initialise a member in the initialisation list, that is the
unique inisialization.


这篇关于一些C ++特定的面试问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆