I have been writing my code on mbed online compiler for a time.
Recently, I started working on mbed studio because of internet problems.
I imported a program that used to be a compile from an online computer, and there was an error when I compiled it from the mbed studio.
[Error] instanceHeader.hpp@28,28: call to implicitly-deleted copy constructor of 'HCSR04'
[ERROR] In file included from ./main.cpp:12:
./variables/instanceHeader.hpp:28:28: error: call to implicitly-deleted copy constructor of 'HCSR04'
HCSR04 sonar[NUM_SONAR] ={ HCSR04(SONAR0_ECHO, SONAR0_TRIG, SONAR_FILTER_WS,1)};
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./HCSR04_MANAGER/HCSR04.h:57:21: note: copy constructor of 'HCSR04' is implicitly deleted because field 'echo' has a deleted copy constructor
InterruptIn echo; // echo pin
^
./mbed-os/drivers/InterruptIn.h:65:21: note: copy constructor of 'InterruptIn' is implicitly deleted because base class 'NonCopyable<mbed::InterruptIn>' has an inaccessible copy constructor
class InterruptIn : private NonCopyable<InterruptIn> {
^
1 error generated.
First, the compiler (silently) creates a temporary object of HCSR04 by calling its constructor.
Then the compiler tries to assign the temporary object to the first element (member) of the sonar array by copying the temporary HCSR04 object to the memory area of the array’s first element. If there is a copy-constructor defined for the HCSR04 class it will use that one. Otherwise the compiler will define a simple “default” constructor which will copy the data members of the temporary HCSR04 object one by one. If the data member has a copy constructor then the compiler will use it otherwise will again define a simple “default” one.
One data member of the HCSR04 class is of InterruptIn type inheriting the NonCopyable class as you can see below:
class InterruptIn : private NonCopyable<InterruptIn> {
...
The NonCopyable class is in turn defined as:
class NonCopyable {
#ifndef DOXYGEN_ONLY
protected:
/**
* Disallow construction of NonCopyable objects from outside of its hierarchy.
*/
NonCopyable() = default;
/**
* Disallow destruction of NonCopyable objects from outside of its hierarchy.
*/
~NonCopyable() = default;
...
That’s why we cannot define and initialize an array of NonCopyable objects and it’s children.
One solution is to define and initialize an array of dynamic objects (pointers to objects created on the heap).
For example:
HCSR04* sonar[NUM_SONAR] ={ new HCSR04(SONAR0_ECHO, SONAR0_TRIG, SONAR_FILTER_WS,1) };
and “dereferencing” the pointer before calling a member function:
However, what I confuse about is why the online compiler compiles the same code(the array constructor one) well.
Copy-initialization of array members is in place since the C++17 standard. Maybe the online compiler uses an older revision where no copying is involved when an array member is initialized.