简体   繁体   中英

C++: Passing an array to a constructor and saving it in the this object

I would like to do this JavaScript code in C++:

class Example {
    constructor(myArr) {
        this.myArr = myArr;
    }
    test() {
        console.log(myArr[0])
    }
}
var myArr = [1,2,3,4]
var example = new Example(myArr)
example.test()
// prints `1`

My C++ attempt:

#include <iostream>

class Example {
public:
    int myArr[4];
    Example(int myArr[4]);
    void test(void);
};

Example::Example(int myArr[4]) {
    //this.myArr = myArr;
    this->myArr = myArr;
    //myArr = myArr;
}
void Example::test(void) {
    std::cout << this->myArr[0];
}


int main() {
    int myArr[4] = {1,2,3,4};
    Example *example = new Example(myArr);
    example->test();
}

I don't really understand what I'm doing wrong. I tried lots of different things like using this-> instead of this. , but I always get errors. For instance, the current version gives me:

 In constructor 'Example::Example(int*)':
12:17: error: incompatible types in assignment of 'int*' to 'int [4]'

I don't really understand what I'm doing wrong. I specified my array as int myArr[4] everywhere in the code and I can't remember passing an int* anywhere.

#include <iostream>
#include <vector>

class Example {
public:
    std::vector<int> myArr;
    Example(const std::vector<int> & myArr);
    void test();
};

Example::Example(const std::vector<int>& myArr) {
    this->myArr = myArr;
}
void Example::test() {
    std::cout << this->myArr[0];
}


int main() {
    std::vector<int> myVec{1,2,3,4};
    Example example1(myVec);

    // Or directly
    Example example2({1, 2, 3, 4});

    // And is you don't have choice and use raw array
    int myArr[4] = { 1, 2, 3, 4 };
    Example example3(std::vector<int>(myArr, myArr + 4));

    example1.test();
    example2.test();
    example3.test();
}

When passing vector, I recommend to you to use reference, to avoid useless copy of vector

Also, in this example, it's not pertinent to use dynamic allocation for Example . And when you use dynamic allocation, don't forget to delete your object (or better, use smart pointer)

Personal advice :

  • Use of standard container like vector , array , list , map , .... they simplify copy and standard manipulation
  • Use of smart pointer to avoid manual management of dynamical allocated data, which can be difficult (in your case, you forget to delete your main object and you just have one)

Below, the raw array version, for at least c++11, but I recommend to use std::vector or std::array :

#include <iostream>

class Example {
public:
    int * myArr = nullptr;
    std::size_t length = 0;
    Example(const int * const myArr, std::size_t length);
    Example(const Example & old); // To respect rule of 5
    Example(Example && old); // To respect rule of 5
    Example &operator=(const Example &rhs); // To respect rule of 5
    Example &operator=(Example &&rhs); // To respect rule of 5
    ~Example();
    void test();
};

Example::Example(const int * const myArr, std::size_t length) {
    this->myArr = new int[length];
    this->length = length;
    for(std::size_t i = 0; i < length; ++i) {
        this->myArr[i] = myArr[i];
    }
}

// Copy constructor
Example::Example(const Example &old) {
    *this = old;
}

// Move constructor
Example::Example(Example &&old) {
    *this = std::move(old);
}

// Copy assignement operator
Example &Example::operator=(const Example & rhs)
{
    length = rhs.length;
    for(std::size_t i = 0; i < length; ++i) {
        myArr[i] = rhs.myArr[i];
    }
    return *this;
}

// Move assignement operator
Example &Example::operator=(Example &&rhs)
{
    myArr = rhs.myArr;
    length = rhs.length;

    rhs.myArr = nullptr;
    rhs.length = 0;

    return *this;
}

void Example::test() {
    std::cout << this->myArr[0];
}

Example::~Example()
{
    if (myArr != nullptr)
        delete myArr;
}


int main() {
    int myArr[4] = {1,2,3,4};
    Example example1(myArr, 4);

    example1.test();
}

I feel it might be a good idea to share with you a more C++ oriented way to do this:

#include <iostream>
#include <array>                // uses same amount of memory as a standard array
                                // but has a set size unlike std::vector
class Example {
public:
    std::array<int, 4> myArr;
    Example(const std::array<int, 4>& myArr);
    void test(void);
};

Example::Example(const std::array<int, 4>& myArr)
    : myArr{myArr}              // initialize myArr directly using a member 
                                // initializer list.
{}

void Example::test(void) {
    std::cout << myArr[0];      // no need for this-> as it is implicit
}

int main() {
    // prefer brace initialization
    std::array<int, 4> myArr{1, 2, 3, 4};

    Example example{myArr};     // avoid pointer so that delete does not have 
                                // to be called explicitly

    example.test();

    // example and myArr will have their destructors
    // called automatically when they go out of scope 
    // as per RAII
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM