[C++] Perguntas da entrevista

1. Diz-se que C++ é uma linguagem orientada a objetos. Você pode [expandir] apresentar as três características da orientação a objetos?

Encapsulamento: O encapsulamento é uma ideia de gerenciamento centralizado que combina dados internos e métodos de implementação sem expor os dados internos e os métodos de implementação ao mundo externo. Ele fornece apenas algumas interfaces para o mundo externo para concluir chamadas de função e operações de dados. A segurança e a consistência de dados são garantidos.

Herança: Herança significa que uma classe pode herdar os métodos e dados de outra classe, o que pode melhorar a reutilização do código e estabelecer o relacionamento entre as classes.

Polimorfismo: Polimorfismo significa que o mesmo método possui comportamentos diferentes para objetos diferentes, o que melhora a flexibilidade do código.

2. Você já entendeu a implementação subjacente do polimorfismo?

A camada inferior do polimorfismo é implementada através de um ponteiro de função virtual. O ponteiro de função virtual aponta para uma tabela de funções virtuais. O endereço de cada função é armazenado na tabela de funções virtuais. A tabela de funções virtuais é uma matriz de ponteiros, e o virtual tabela de funções armazena ponteiros de função., quando uma expressão satisfaz o polimorfismo, ela determina o tipo não na fase de compilação, mas na fase de execução para determinar que tipo é, e então chama a tabela de funções virtuais de acordo com diferentes objetos.

3. Como a função virtual é implementada no nível inferior?

Quando uma função em uma classe é virtualmodificada, um ponteiro de função virtual aparecerá e o ponteiro de função virtual aponta para a tabela de funções virtuais.

4. (Cenário 1) Existem duas classes cujas variáveis ​​de instância e métodos de função que elas suportam são exatamente iguais. Uma classe implementa uma função virtual. Qual é a diferença entre elas? Eles ocupam a mesma quantidade de memória ao gerar um objeto de instância?

A memória ocupada é diferente. Se a função virtual for implementada, haverá mais um ponteiro de função virtual, que ocupará 4/8 bytes de espaço, e a memória ocupada será diferente.

5. (Cenário 2) Existem quatro classes B e C herdando de A, e D herdando de B e C (herança múltipla).Há uma função pública em A, e então cada um de B e C a reescreveu, e então quer chamá-lo de D. Como chamar a implementação de B ou C?

Use diretamente o operador de domínio de classe ::para especificar a chamada de domínio de classe.

6. Ainda é o cenário acima. Existe uma variável pública em A. B e C herdam de A, e D herda de B e C. Depois, existem várias variáveis ​​públicas armazenadas em D (tem me orientado, um, Dois porções, três porções)

Esta questão precisa ser discutida em categorias.

Herança ordinária: duas ações (uma ação para B e C).

Herança virtual: uma via, colocada diretamente na área pública.

7. Qual é a diferença entre malloc e novo?

1. O tipo de retorno de malloc é (void*) e requer conversão manual.

2. malloc retorna um erro de alocação de memória NULL, enquanto new lança uma exceção.

3. Quando new aloca memória, ele chamará o construtor para inicialização e malloc precisará ser inicializado manualmente.

4. Quando malloc aloca memória, você precisa calcular manualmente quanto espaço abrir, mas new não.

5. Novo usa delete para liberar memória e malloc usa free.

6. A camada inferior de new também é chamada operator newe operator newmalloc também é chamada para realizar a alocação de memória.

8. Além de alocar memória, new possui outras operações adicionais além de malloc?

O construtor será chamado para inicialização.

9. New na verdade faz duas coisas, uma é alocar memória e a outra é chamar o construtor da instância. Você já entendeu que new só pode realizar uma operação? Por exemplo, alocar apenas memória sem chamar o construtor ou apenas chamar o construtor sem alocar memória?

Nenhuma memória é alocada, apenas o construtor é chamado: position new( placement new) também operator new.

O construtor não é chamado, apenas a memória é alocada: new (std::nothrow) type.

10. Calcule o tamanho das duas estruturas a seguir.

struct {
    
    
    char A;
    char B;
    int C;
}

struct {
    
    
    char A;
    int C;
    char B;
}

Problemas de alinhamento de memória.

O primeiro tem 8 bytes.

O segundo tem 12 bytes.

11. Vejo que você escreveu que conhece STL. Você aprendeu sobre ponteiros inteligentes?

1. O primeiro ponteiro inteligente foi auto_ptr, mas esse ponteiro inteligente não realizou totalmente as funções do ponteiro. Ele percebeu principalmente RAIIa ideia de transferência de permissão.

2. Então pareceu unique_ptrque a abordagem deste ponteiro inteligente era bastante grosseira, não permitindo a cópia e proibindo a chamada de construtores de cópia.

3. Então shared_ptr, este ponteiro inteligente resolve o problema original: um endereço só pode ser apontado por um ponteiro inteligente, caso contrário o mesmo bloco de memória será liberado duas vezes. Solução: Use contagem de referência. Mas ainda há o problema das referências circulares.

4. weak_ptr, um ponteiro inteligente auxiliar, utilizado para resolver o problema de referência circular, permitindo que a variável do ponteiro interno weak_ptrseja utilizada para representá-lo, weak_ptrsem modificar a contagem de referência, para que possa resolver muito bem o problema de referência circular.

12. Dê um exemplo de ponteiro inteligente em um cenário prático? Por que usá-lo? Como usá-lo? Tudo bem se eu não usar?

Quando se trata de segurança de exceções, é melhor usar ponteiros inteligentes.

Por exemplo, o seguinte código:

#include<iostream>
using namespace std;

int div()
{
     
     
	int a, b;
	cin >> a >> b;
	if (b == 0)
		throw invalid_argument("除0错误");
	return a / b;
}
void Func()
{
     
     
	// 1、如果p1这里new 抛异常会如何?
	// 2、如果p2这里new 抛异常会如何?
	// 3、如果div调用这里又会抛异常会如何?
	int* p1 = new int;
	int* p2 = new int;
	cout << div() << endl;
	delete p1;
	delete p2;
}
int main()
{
     
     
	try
	{
     
     
		Func();
	}
	catch (exception& e)
	{
     
     
		cout << e.what() << endl;
	}
	return 0;
}

A não utilização de ponteiros inteligentes levará a problemas como a não liberação de várias memórias ou a falta de abertura de espaço.

Os ponteiros podem ser usados ​​sem ponteiros? Sim, mas requer várias camadas de captura de exceções, o que é muito problemático e a legibilidade do código torna-se muito baixa.

13. Você acabou de mencionar que a camada inferior de shared_ptr é compartilhada usando uma contagem de referência.Você conhece outros métodos de gerenciamento de memória?

O mecanismo automático de reciclagem de memória em JAVA usa um conjunto relativamente complexo de algoritmos para calcular o tempo de reciclagem e não há um entendimento profundo dos detalhes.

14. Você já entendeu o mecanismo de expansão dos contêineres de vetores comumente usados ​​em STL?

O mecanismo de expansão é diferente em plataformas diferentes.

vs: 1,5 vezes.

Linux: 2x.

Expansão consiste em reabrir um espaço, copiar o conteúdo original e depois destruir o espaço original.

15: Posso expandir a capacidade três vezes?

Sim, mas pode resultar em muito desperdício de espaço.

16: Você conhece a capacidade inicial do vetor? Quando ocorrerá a expansão inicial?

A capacidade será expandida quando um elemento for adicionado pela primeira vez, e a primeira expansão geralmente será definida como 8 ou 16.

Acho que você gosta

Origin blog.csdn.net/AkieMo/article/details/132278215
Recomendado
Clasificación