Ir ao conteúdo
  • Cadastre-se

C++ Inicializar array com elementos iguais a 0.


Visitante
Ir à solução Resolvido por arfneto,

Posts recomendados

porque os elementos do array estão com lixo mesmo eu inicializando com 0?

obs: No caso o erro seria no ultimo trecho de código do construtor.

 

class Array {
private:
    int capacity; //capacidade total do Array
    int *ptr;     //ponteiro para o array de inteiros

public:
    Array(int capacity) {
        //inicialize this->capacity com capacity
        this->capacity = capacity;
        //crie memória dinamicamente para this->ptr com tamanho capacity
        this->ptr = new (nothrow) int [ capacity ];
        if(ptr == nullptr){
            cout << "não foi possível alocar memoria" << endl;
        }
        //o vetor é inicializado com zeros
        for(int i=0; i<capacity; i++){
            this->ptr[i] = 0;
        }
    }
  
  
  
terminal:
  
PS C:\Users\rlima\Documents\ED 2021.2\Array dinamico - OOP> g++ -o main solver.cpp
PS C:\Users\rlima\Documents\ED 2021.2\Array dinamico - OOP> .\main
init 5 
$init 5
show
$show
[ 14618520 14619608 1852400672 1667853665 539828335 ]

 

7 minutos atrás, Prodigy085 disse:

porque os elementos do array estão com lixo mesmo eu inicializando com 0?

obs: No caso o erro seria no ultimo trecho de código do construtor.

 

class Array {
private:
    int capacity; //capacidade total do Array
    int *ptr;     //ponteiro para o array de inteiros

public:
    Array(int capacity) {
        //inicialize this->capacity com capacity
        this->capacity = capacity;
        //crie memória dinamicamente para this->ptr com tamanho capacity
        this->ptr = new (nothrow) int [ capacity ];
        if(ptr == nullptr){
            cout << "não foi possível alocar memoria" << endl;
        }
        //o vetor é inicializado com zeros
        for(int i=0; i<capacity; i++){
            this->ptr[i] = 0;
        }
    }
  
  
  
terminal:
  
PS C:\Users\rlima\Documents\ED 2021.2\Array dinamico - OOP> g++ -o main solver.cpp
PS C:\Users\rlima\Documents\ED 2021.2\Array dinamico - OOP> .\main
init 5 
$init 5
show
$show
[ 14618520 14619608 1852400672 1667853665 539828335 ]

 

 

 

Aqui a main caso precise:

 

 

#include <iostream>
#include <sstream>
#include "array.h"
using namespace std;

int main(){
    string line, cmd;
    int value;
    Array v(0);
    while(true){
        getline(cin, line);
        cout << "$" << line << endl;
        stringstream ss(line);
        ss >> cmd;
        if(cmd == "end"){
            break;
        } else if(cmd == "init"){
            ss >> value;
            v = Array(value);
        } else if(cmd == "status"){
            cout << " capacity:" << v.getCapacity() << "\n";
        } else if(cmd == "insert"){
            int index;
            ss >> value;
            ss >> index;
            v[index] = value;
        } else if(cmd == "show"){
            cout << v << endl;
        } else {
            cout << "fail: comando invalido\n";
        }
    }
}

 

Link para o comentário
Compartilhar em outros sites

Olá!

Você programou uma sobrecarga do operador [<<]?

22 horas atrás, Prodigy085 disse:
if(cmd == "show"){
            cout << v << endl;

Talvez, uma das falhas está no programa da saída!

 

Não entendo completamente, logo desculpa antecipada caso esteja em sua programação e eu que não tenho avistado, ainda!

[:)

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

4 horas atrás, mauro_b disse:

Olá!

Você programou uma sobrecarga do operador [<<]?

Talvez, uma das falhas está no programa da saída!

 

Não entendo completamente, logo desculpa antecipada caso esteja em sua programação e eu que não tenho avistado, ainda!

[:)

Boa noite, você tinha razão, o erro realmente era na função de imprimir os valores na tela (penúltima função do código abaixo) mesmo sem ver a função você me direcionou ao local do erro, obrigado cara!

 

Vou deixar toda a header aqui para fins de estudo de terceiros.

 

#include <iostream>
using namespace std;

class Array {
private:
    int capacity; //capacidade total do Array
    int *ptr;     //ponteiro para o array de inteiros

public:
    Array(int capacity) {
        //inicializando this->capacity com capacity
        this->capacity = capacity;
        //criando memória dinamicamente para this->ptr com tamanho capacity
        this->ptr = new (nothrow) int [ capacity ];
        if(ptr == nullptr){
            cout << "não foi possível alocar memoria" << endl;
        }
        //o vetor é inicializado com zeros
        for(int i = 0; i<capacity; i++){
            this->ptr[i] = 0;
        }

    }

    //como seu Array tem atritutos do tipo ponteiros, você precisa criar um
    //construtor de cópia e um operador de atribuição ou terá erros do tipo double-free

    //O operador de atribuição será invocado quando você fizer um Array receber outro
    //Exemplo:
    //Array vec(4);
    //vec = Array(6);
    //nesse ponto, os atributos de this já foram inicializados, 
    //mas você precisa alterá-los para copiar os valores de other
    void operator=(const Array& other) {
        //inicialize this->capacity com other.capacity
        this->capacity = other.capacity;
        //se this->ptr não for nulo, devolva a memória com delete[]
        if(this->ptr == nullptr){
            delete[] this->ptr;

        }
        //crie nova memória para this->ptr do tamanho de other.capacity
        this->ptr = new (nothrow) int [ other.capacity];
        if(this->ptr == nullptr){
            cout << "não foi possível alocar memoria" << endl;
        }
        //copie os dados de other.ptr para this->ptr
        for(int i = 0; i<this->capacity; i++){
            this->ptr[i] = other.ptr[i];
        }
    }

    //aqui você ensina seu Array a ser criado a partir de outro Array
    //Exemplo: 
    //Array v(4);
    //Array v2(v);
    Array(const Array& other){
        *this = other;
    }

    // Destrutor
    ~Array(){
        delete this->ptr;
        this->ptr = nullptr;
    }

    // getter
    int getCapacity() {
        return this->capacity;
    }

    //esse é o operador de igualdade sobrecarregado
    //essa função determina se os dois Arrays são iguais e devolve true,
    //caso contrário devolve false
    bool operator==(const Array& other) {
        // checa se this->capacity é diferente de other.capacity
        if(this->capacity != other.capacity){
            return false;
        }
        // checa se this->ptr tem os mesmos elementos que other.ptr
        for(int i = 0; i<this->capacity; i++){
            if(this->ptr[i] != other.ptr[i]){
                return false;
            }
        }
        return true;
    }

    bool operator!=(const Array& other) {
        //aqui você não precisa fazer nada, basta utilizar 
        // o operador de igualdade que você já implementou logo acima
        return !(*this == other); // invoca operator==
    }

    // Esse é o toString do C++
    // tudo que enviar para out, é como se estivesse enviando 
    // para saída padrão basta entender o funcionamento
    friend ostream& operator<<(ostream &out, const Array& array){
        out << "[ ";
        for(int i = 0; i < array.capacity; ++i)
            out << array.ptr[i] << " ";
        out << "]";
        return out;
    }

    //esse é o operador de indexação sobrecarregado
    //ele permite que possamos acessar e/ou modificar o valor 
    //em um certo índice do Array.
    int& operator[](int index) {
        return ptr[index];
    }
};

 

Link para o comentário
Compartilhar em outros sites

  • Solução
Em 01/01/2022 às 20:57, Prodigy085 disse:

Boa noite, você tinha razão, o erro realmente era na função de imprimir os valores na tela (penúltima função do código abaixo) mesmo sem ver a função você me direcionou ao local do erro,

 

Acho que o maior erro está mesmo na linha 11 em main, fora do loop, onde deixou um 
 

       Array  v(0); 

 

que não faz sentido e gera comportamento indefinido --- UB.

 

Em 01/01/2022 às 20:57, Prodigy085 disse:

Vou deixar toda a header aqui para fins de estudo de terceiros

 

header em português é cabeçalho, masculino. Provavelmente estaria melhor escrevendo UM header.

 

Imagino que tenha uma razão para reescrever array, que está presente em std usando o include apropriado, <array>.

 

Como tem vários operadores redefinidos vou deixar umas notas sobre isso, algo que provavelmente receberia em sua empresa se ela tiver um comitê de revisão, ou de seu professor, considerando as recomendações comuns de boas práticas desde 2010 mais ou menos.

 

Tem ainda uns erros em seu programa, que vou listar no texto.

 

Escrevo isso "tudo" porque pode ser um exemplo para quem precisa de uma classe assim. Sugiro acompanhar o exemplo.

 

Isso é problemático em seu programa:
 

    Array v(0);


Porque precisa disso? Espere até ter um valor e apenas então crie `v`. Acessar esse ponteiro leva a um comportamento indefinido, o popular `UB`. E nunca é bom.

 

Lendo um pouco mais seu código
 

   Array  v(0);
    while (true)
    {
        getline(cin, line);
        cout << "$" << line << endl;
        stringstream ss(line);
        ss >> cmd;
        if (cmd == "end") { break; }
        else if (cmd == "init")
        {
            ss >> value;
            v = Array(value);
        }


 Então para que declarou `v` fora do loop se a cada iteração está destruindo `v` ao identificar `value` --- na linha 22 --- exatamente como eu disse para fazer?

 

Apenas apague aquela linha.

 

A classe Array

 

Imagino que precise mesmo disso, como um exercício ou um teste, já que C++ tem a classe `array` disponível, bem similar. E vários outros containers.

 

Sobre essa implementação
 

   private:
    int  capacity;  // capacidade total do Array
    int* ptr;       // ponteiro para o array de inteiros

 

Isso provavelmente deveria ser implementado usando unique_ptr<int[]> desde 2010 mas não vou colocar no exemplo porque imagino que precise da construção como escreveu.

 

  public:
    Array(int capacity)
    {
        // inicializando this->capacity com capacity
        this->capacity = capacity;
        // criando memória dinamicamente para this->ptr com tamanho
        // capacity
        this->ptr = new (nothrow) int[capacity];
        if (ptr == nullptr)
        {
            cout << "não foi possível alocar memoria" << endl;
        }
        // o vetor é inicializado com zeros
        for (int i = 0; i < capacity; i++) { this->ptr[i] = 0; }
    }

 

Implemente o construtor padrão ou invalide o mesmo --- =delete --- para deixar claro pata você e quem ler seu programa que sabe o que está acontecendo.

 

    // inicializando this->capacity com capacity
    this->capacity = capacity;


Evite esse tipo de comentário. É óbvio o que está fazendo.

 

E C++ não é java. Não precisa escrever esses this toda hora. Prefira o simples, algo como

 

Array::Array(int capacity) : capacity(capacity)
{
    ptr = new (nothrow) int[capacity];
    if (ptr == nullptr)
    {
        cerr << "não foi possível alocar memoria" << endl;
        terminate();
    }
    for (int i = 0; i < capacity; i++) ptr[i] = 0;
}

 

Não escreva na tela --- cout --- em um construtor . Isso pode simplesmente impedir o uso de sua classe em outros casos. Se achar que precisa MESMO escrever use cerr e não cout. E se for algo realmente sério chame terminate() e aborte o programa e pronto.

Pode colocar um limite interno a essa capacidade e se passar disso cancelar ou limitar a esse valor. E se não conseguir alocar um valor suposto razoável o computador deve estar numa situação tão instável que pode ser melhor cancelar mesmo.

 

    // o vetor é inicializado com zeros
    for (int i = 0; i < capacity; i++) { this->ptr[i] = 0; }


Mesmo sem o comentário dá pra ler que o vetor será inicializado com zeros. E não precisa dessas chaves nem do this. Veja o exemplo acima.

 

    // como seu Array tem atritutos do tipo ponteiros, você precisa
    // criar um construtor de cópia e um operador de atribuição ou terá
    // erros do tipo double-free

    // O operador de atribuição será invocado quando você fizer um Array
    // receber outro Exemplo: Array vec(4); vec = Array(6); nesse ponto,
    // os atributos de this já foram inicializados, mas você precisa
    // alterá-los para copiar os valores de other

 

Pois é. Note o segundo exemplo:

    vec = Array(6);


 Array(6) é um r-value e vai ser copiado a toa. Por essa razão ao implementar uma classe dessa deve escrever TAMBÉM o move constructor e o move assignment porque não há razão para copiar a classe toda. E nesse caso e o compilador não vai conseguir perceber isso. No seu código basta copiar os ponteiros e invalidar a origem. Veja no exemplo ao final.

 

   // se this->ptr não for nulo, devolva a memória com delete[]
   if (this->ptr == nullptr) { delete[] this->ptr; }

 

Algo errado aqui... Acho que inverteu a condição.  E não precisa do this nem das chaves.

 

Prefira algo assim

 

    ~Array()
    { 
        delete this->ptr;
        this->ptr = nullptr; 
    }


Não precisa desses this. E o delete está errado: deve usar delete [].

 

    // getter
    int getCapacity() { return this->capacity; }

 

Todos os containers implementam size() para retornar um tamanho. Talvez não acha razão para reinventar isso. E não precisa do this e não deve retornar um int. Prefira algo sem sinal. Algo como
 

    size_t Array::size() { return capacity; }

 

Sobre esse operador

 

    // esse é o operador de igualdade sobrecarregado
    // essa função determina se os dois Arrays são iguais e devolve
    // true, caso contrário devolve false
    bool operator==(const Array& other)
    {
        // checa se this->capacity é diferente de other.capacity
        if (this->capacity != other.capacity) { return false; }
        // checa se this->ptr tem os mesmos elementos que other.ptr
        for (int i = 0; i < this->capacity; i++)
        {
            if (this->ptr[i] != other.ptr[i]) { return false; }
        }
        return true;
    }

 

Pois é:
 

está claro que a implementação de == retorna bool e esse comentário não acrescenta nada. Não precisa dessas chaves todas e desses this. Prefira o simples e clássico
 

    bool Array::operator==(const Array& other)
    { 
        if (capacity != other.capacity) return false;
        for (int i = 0; i < capacity; i++) 
            if (ptr[i] != other.ptr[i])
                return false;
        return true;
    }

 

Sobre a redefinição de <<

 

   // Esse é o toString do C++
    // tudo que enviar para out, é como se estivesse enviando
    // para saída padrão basta entender o funcionamento
    friend ostream& operator<<(ostream& out, const Array& array)
    {
        out << "[ ";
        for (int i = 0; i < array.capacity; ++i)
            out << array.ptr[i] << " ";
        out << "]";
        return out;
    }

 

Não, esse não é o operador toString do C++.

 

toStream talvez? Imagino que pretendia escrever
 

    cout << Array(12);


como um WriteLn(toString() ) de C++. Mas é bem diferente. Essa redefinição retorna uma referência a stream e não uma string.

 

E porque não mostrar o valor de capacity?

Vai deixar para o cara contar um por um na saída? E se forem centenas?


Prefira

`

ostream& operator<<(ostream& out, const Array& array)
{
    out << "(" << array.capacity << ") [ ";
    for (int i = 0; i < array.capacity; ++i)
        out << array.ptr[i] << " ";
    out << "]\n";
    return out;
}

 

que deve mostrar algo assim
 

(6) [ 0 0 0 0 0 0 ]

 

para este enorme programa
 

#include "array.h"
int main(void)
{
    std::cout << Array(6);
    return 0;
}

 

 

UM EXEMPLO COMPLETO

 

A saída 

 

(6) [ 0 0 0 0 0 0 ]
Array destructor
cria 'v'
copia para 'outro'
copy constructor
assignment operator
mostra 'outro'
(5) [ 0 0 0 0 0 ]
cria 'um'
'um' agora tem 3 elementos
mostra 'um'
(3) [ 0 0 0 ]
move algo para 'um'
move assignment
Array destructor
'um' agora tem 6 elementos
(6) [ 0 0 0 0 0 42 ]
vai encerrar: destroi todos
Array destructor
Array destructor
Array destructor

 

Desse programa

 

#include "array.h"
int main(void)
{
    { std::cout << Array(6); }
    cout << "cria 'v'\n";
    Array v(5);
    cout << "copia para 'outro'\n";
    auto outro = v;
    cout << "mostra 'outro'\n";
    cout << outro;
    cout << "cria 'um'\n";
    auto um = Array(3);
    cout << "'um' agora tem " << um.size() << " elementos\n";
    cout << "mostra 'um'\n";
    cout << um;
    cout << "move algo para 'um'\n";
    um = Array(6);
    um[5] = 42; // testa o operador
    cout << "'um' agora tem " <<
        um.size() << " elementos\n";
    cout << um;
    cout << "vai encerrar: destroi todos\n";
    return 0;
}

 

E assim acho que pode acompanhar a execução dos métodos todos.

 

A classe Array

 

Prefira a classe assim, sem implementação porque pode ver muito melhor o que é a classe sem ter que seguir telas e telas de código para ver um conjunto simples como esse

 

#include <iostream>
using namespace std;

class Array
{
public: 
    Array(int capacity);
    Array() = delete;
    Array(const Array&); // copy
    Array(const Array&&) noexcept; // move
    ~Array();
    
public:
    const Array& operator=(const Array&); // copy
    Array&       operator=(Array&&) noexcept; // move
    bool operator==(const Array&); 
    bool operator!=(const Array&);
    int& operator[](int);

    size_t size();

    friend ostream& operator<<(ostream& out, const Array& array);

   private:
    int  capacity;
    int* ptr;  // o array
};

 

Uma implementação de Array

 

#include "Array.h"

Array::Array(int capacity) : capacity(capacity)
{
    ptr = new (nothrow) int[capacity];
    if (ptr == nullptr)
    {
        cerr << "não foi possível alocar memoria" << endl;
        terminate();
    }
    for (auto i = 0; i < capacity; i++) ptr[i] = 0;
}

const Array& Array::operator=(const Array& other)
{
    cerr << "assignment operator\n";
    if (&other == this) return *this; 
    capacity = other.capacity;
    if (ptr != nullptr) delete[] ptr;
    ptr = new (nothrow) int[other.capacity];
    if (ptr == nullptr)
    {
        cerr << "não foi possível alocar memoria" << endl;
        terminate();
    }
    for (auto i = 0; i < capacity; i++)
        ptr[i] = other.ptr[i];
    return *this;
}

Array& Array::operator=(Array&& other) noexcept
{
    cerr << "move assignment\n";
    delete[] ptr;
    capacity = other.capacity;
    ptr = other.ptr;
    other.ptr = nullptr;
    return *this;
}

Array::Array(const Array& other)
{
    cerr << "copy constructor\n";
    *this = other;
}

Array::Array(const Array&& other) noexcept
{
    cerr << "move constructor\n";
    delete[] ptr;
    ptr = other.ptr;
    capacity = other.capacity;
}

Array::~Array()
{
    cerr << "Array destructor\n";
    delete [] ptr;
    ptr = nullptr;
}

size_t Array::size() { return capacity; }

bool Array::operator==(const Array& other)
{
    if (capacity != other.capacity) return false;
    for (auto i = 0; i < capacity; i++)
        if (ptr[i] != other.ptr[i])
            return false;
    return true;
}

bool Array::operator!=(const Array& other)
{
    return not (*this == other);
}

int& Array::operator[](int index)
{ 
    return ptr[index];
}

// fim dos metodos da classe //

// esse poderia estar em outro lugar
// ja que não e um metodo da classe

ostream& operator<<(ostream& out, const Array& array)
{
    out << "(" << array.capacity << ") [ ";
    for (auto i = 0; i < array.capacity; ++i)
        out << array.ptr[i] << " ";
    out << "]\n";
    return out;
}

 

Sugiro rodar isso em sua máquina e comparar. Esse é o modo comum de escrever essas coisas.

 

Note que o uso de new e delete ou new[] e delete[] é absolutamente desencorajado em C++ há pelo menos uma década.

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@arfneto Infelizmente, meu professor não estimula o uso e nem ensina essas boas maneiras, talvez eu deva ler mais os livros, apesar de preferir assistir vídeo-aula. Eu tenho um e-book do Bianchi (Estrutura de dados e técnicas de programação), mas é de 2013, parece muito desatualizado? Se tiver alguma sugestão, ajudaria bastante.

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Prodigy085 disse:

 Infelizmente, meu professor não estimula o uso e nem ensina essas boas maneiras, talvez eu deva ler mais os livros, apesar de preferir assistir vídeo-aula. Eu tenho um e-book do Bianchi (Estrutura de dados e técnicas de programação), mas é de 2013, parece muito desatualizado? Se tiver alguma sugestão, ajudaria bastante.

 

Eu te escrevi um certo número de sugestões. Entendeu tudo que eu expliquei? Rodou em sua máquina? Provavelmente é o que um grupo de revisão --- code review --- numa empresa grande diria sobre aquela classe em seu programa. 2013 é um pouco antigo. A linguagem evoluiu muito em '14, '17 e '20. Mas o que escrevi acima acho que rodava em 2013.

 

Entendeu o que estava errado em seu programa? As diferenças do que eu te mostrei? Entendeu main() no exemplo?

 

 

 

 

1 hora atrás, Prodigy085 disse:

 Infelizmente, meu professor não estimula o uso e nem ensina essas boas maneiras, talvez eu deva ler mais os livros, apesar de preferir assistir vídeo-aula. Eu tenho um e-book do Bianchi (Estrutura de dados e técnicas de programação), mas é de 2013, parece muito desatualizado? Se tiver alguma sugestão, ajudaria bastante.

 

Eu te escrevi um certo número de sugestões. Entendeu tudo que eu expliquei? Rodou em sua máquina? Provavelmente é o que um grupo de revisão numa empresa grande diria sobre aquela classe. 2013 é um pouco antigo. A linguagem evoluiu muito em '14, '17 e '20. Mas o que escrevi acima acho que rodava em 2013.

 

Entendeu o que estava errado em seu programa? As diferenças do que eu te mostrei? Entendeu main() no exemplo?

 

Mais ainda: entendeu as notas que eu deixei sobre os comentários de seu programa original? Sobre algumas coisas que não são como está lá escrito...

 

 

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@arfneto Vou citar o que n entendi.

No trecho de código onde eu declaro os atributos privados, como você implementaria usando unique_ptr<int[ ]>? Nunca ouvi falar sobre isso, e quais as vantagens.

Agora sobre o "cerr", eu entendi que o cout no construtor é um problema, mas qual a diferença entre ambos?

Na função size(), você disse que não deve retornar um inteiro, pode explicar o motivo? 

Por fim, por que o uso de new e delete é desencorajado em C++?

 

Link para o comentário
Compartilhar em outros sites

12 horas atrás, Prodigy085 disse:

ou citar o que n entendi.

No trecho de código onde eu declaro os atributos privados, como você implementaria usando unique_ptr<int[ ]>? Nunca ouvi falar sobre isso, e quais as vantagens.

Agora sobre o "cerr", eu entendi que o cout no construtor é um problema, mas qual a diferença entre ambos?

Na função size(), você disse que não deve retornar um inteiro, pode explicar o motivo? 

Por fim, por que o uso de new e delete é desencorajado em C++?

 

São muitas diferenças entre o modo meio C que tinha no original e isso que te mostrei. E muito do que estava comentado estava errado. Mesmo o modo de escrever não está bom. Para uma classe assim é melhor usar dois arquivos. Sempre é exceto se usa templates

 

Para que unique_ptr<>?

 

Seu programa tinha um erro num delete que era pra ser delete[] por exemplo. unique_ptr<> gerencia a memória sózinho e libera quando não estiver em uso. Assim MUITOS erros comuns são evitados e o custo é quase zero.

 

Por isso o uso de new/delete ou malloc/free é desencorajado desde 2011.

 

A classe Array sem new

 

#include <iostream>
#include <memory>
using namespace std;

class Array
{
public: 
    Array(int capacity);
    Array() = delete;
    Array(const Array&); // copy
    Array(const Array&&) noexcept; // move
    ~Array() = default;

   public:
    const Array& operator=(const Array&); // copy
    Array&       operator=(Array&&) noexcept; // move
    bool operator==(const Array&); 
    bool operator!=(const Array&);
    int& operator[](int);

    size_t size();

    friend ostream& operator<<(ostream& out, const Array& array);

   private:
    int  capacity;
    unique_ptr<int[]> ptr;  // o array
};

 

Note que nem precisa mais do destrutor, e pode declarar como

 

    ~Array() = default;

 

Uma implementação de Array sem new/delete new[]/delete[]

 

#include "Array.h"

Array::Array(int capacity) : capacity(capacity)
{
    ptr = make_unique_for_overwrite<int[]>(capacity);
    for (auto i = 0; i < capacity; i++) ptr[i] = 0;
}

Array::Array(const Array& other)
{
    cerr << "copy constructor\n";
    *this = other;
}

Array::Array(const Array&& other) noexcept
{
    cerr << "move constructor\n";
    ptr.reset(other.ptr.get());
    capacity = other.capacity;
}

const Array& Array::operator=(const Array& other)
{
    cerr << "assignment operator\n";
    if (&other == this) return *this; 
    capacity = other.capacity;
    ptr = make_unique_for_overwrite<int[]>(capacity);
    if (ptr == nullptr)
    {
        cerr << "não foi possível alocar memoria" << endl;
        terminate();
    }
    for (auto i = 0; i < capacity; i++)
        ptr[i] = other.ptr[i];
    return *this;
}

Array& Array::operator=(Array&& other) noexcept
{
    cerr << "move assignment\n";
    capacity = other.capacity;
    ptr = std::move(other.ptr);
    other.ptr.release();
    return *this;
}

bool Array::operator==(const Array& other)
{
    if (capacity != other.capacity) return false;
    for (auto i = 0; i < capacity; i++)
        if (ptr[i] != other.ptr[i])
            return false;
    return true;
}

bool Array::operator!=(const Array& other)
{
    return not (*this == other);
}

int& Array::operator[](int index)
{ 
    return ptr[index];
}

size_t      Array::size() { return capacity; }

// fim dos metodos da classe //

// esse poderia estar em outro lugar
// ja que não e um metodo da classe

ostream& operator<<(ostream& out, const Array& array)
{
    out << "(" << array.capacity << ") [ ";
    for (auto i = 0; i < array.capacity; ++i)
        out << array.ptr[i] << " ";
    out << "]\n";
    return out;
}

 

É mais simples

 

12 horas atrás, Prodigy085 disse:

Agora sobre o "cerr", eu entendi que o cout no construtor é um problema, mas qual a diferença entre ambos?

 

Simples: o construtor que escreve na tela é um porre porque se você tem a tela arrumadinha e quer tratar o erro no programa já era. Mas se precisa mesmo dos cout pode usar cerr porque na hora de rodar o programa basta acrescentar 2>NUL se roda Windows e todas as mensagens somem. Ou usar 2>erros.txt e salvar em arquivo.

 

É o mesmo caso de stderr em C. Assim não precisa mexer no programa que está em teste até achar que é hora de tirar as mensagens.

 

Há outras opções, como usar assert()

 

12 horas atrás, Prodigy085 disse:

Na função size(), você disse que não deve retornar um inteiro, pode explicar o motivo? 

 

Simples: se usar um char por exemplo vai poder usar de -128 a 127. Mas se usar unsigned char pode usar de 0 a 255. Como o tamanho não pode ser negativo vai perder metade do tamanho só por causa do sinal que não vai usar. Por isso todos containers retornam unsigned, como size_t por exemplo.

Link para o comentário
Compartilhar em outros sites

50 minutos atrás, Prodigy085 disse:

Excelente explicação, esse tópico me agregou bastante conhecimento, muito obrigado!

 

Marque o tópico que tem o programa completo e a explicação do erro inicial (UB), ajudando assim outros que tenham problema semelhante a ir mais rápido a uma solução

Link para o comentário
Compartilhar em outros sites

16 minutos atrás, Prodigy085 disse:

Isso é possível mesmo já tendo marcado outra parte como solução? porque eu já tinha marcado antes de você aparecer.

:) Não tenho ideia. Não é assim importante, mas muitas vezes as pessoas não tem paciência de ler todos os posts do tópico, em especial se passar de uma tela :D 

 

Muitas vezes me perguntam coisas que estavam lá no texto mas não foram vistas. E nesse caso o problema de seu programa era aquela declaração inicial v(0). Mas como tem aquele exemplo de classe com todos os construtores e operadores comuns inclusive os de move seria legal se fosse visto antes de tudo.

 

Se for possível o que perguntou imagino que seja apenas o caso de remarcar.

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...