This question already has answers here:
I defined a non-copy constructor; will a copy constructor still be implicitly defined?
(3 answers)
Closed 6 years ago.
I am trying to learn C++ OOP concepts through an online tutorial where I encountered a code snippet illustrating operator overloading.
The code is shown below:
class MyClass{
int var;
public:
Myclass(int value=0){
var = value;
}
Myclass operator+(Myclass &obj){
Myclass newobj;
newobj.var = this->var + obj.var;
return newobj;
}
};
Suppose I call the operator in the main function like so:
int main(){
...
obj3 = obj2 + obj1;
...
}
During earlier tutorials on Classes, I read about why copy constructors require all parameters to be passed by reference since they themselves are the definition of how to copy two class objects. So, as far as I understand, copy constructors are a must when one has to copy objects of a class.
In the above code snippet, it appears to me that the compiler will try to "copy" the values of newobj onto the L_value in the main() function (obj3). But how is this possible without a copy constructor defined. Have I misunderstood something here?
Thank you for your help!
http://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-declared_copy_constructor
If you are using standard C++ 2003 or older copy constructor is always implicitly defined (generated by compiler) for any class T unless:
T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
T has direct or virtual base class that cannot be copied (has deleted, inaccessible, or ambiguous copy constructors);
T has direct or virtual base class with a deleted or inaccessible destructor;
If you are using standard C++ 2011 or newer copy constructor is always implicitly defined (generated by compiler) for any class T unless:
T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
T has direct or virtual base class that cannot be copied (has deleted, inaccessible, or ambiguous copy constructors);
T has direct or virtual base class with a deleted or inaccessible destructor;
T has a user-defined move constructor or move assignment operator;
T is a union and has a variant member with non-trivial copy constructor;
T has a data member of rvalue reference type.
Also keep in mind that
a = b;
is not primarily calling copy-constructor but copy-assignment. That in turn is also implicitly defined (auto-generated) if your class if suitable.
For details see: http://en.cppreference.com/w/cpp/language/copy_assignment#Implicitly-declared_copy_assignment_operator
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a class that has a member of type std::thread, however, when I want to use this class as a member of another class I always get the error that the constructor of the other class was implicitly deleted because std::thread constructor is deleted.
My class with the std::thread member looks as follows:
class VideoSender {
public:
VideoSender() : encoderThread([]{}) {};
~VideoSender(){};
private:
std::thread encoderThread;
};
The other class looks like this:
class RemoteCom {
public:
RemoteCom() : videoSender() {};
~RemoteCom(){};
private:
VideoSender videoSender;
};
I was thinking that I already am properly initializing the std::thread class with (here an empty) function. But I still do get this error, so it seems like somewhere there is still a copy constructor called?
I should also add the I can use the VideoSender class directly without errors. This only happens when used as a member of another class.
Edit
I then initialize RemoteCom like this:
RemoteCom com = RemoteCom();
This is really all there is. I reduced it all to this minimal example, the error still exists.
The syntax
RemoteCom com = RemoteCom();
requires a copy constructor to exist and to be accessible. This is true even if optimization would eliminate the call to the copy constructor.
Replace with
RemoteCom com;
which uses the default constructor directly.
Like you have already noticed, std::thread is not copiable, which is why your class' implicit copy constructor is deleted. For this declaration the compiler could utilize the move constructor
RemoteCom com = RemoteCom();
but it cannot, as it is also deleted. C++ standard section 11.4.5.3 §8:
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
X does not have a user-declared copy constructor,
X does not have a user-declared copy assignment operator,
X does not have a user-declared move assignment operator, and
X does not have a user-declared destructor.
As the VideoSender requires a user-declared destructor, because the thread has to joined before it is destructed, I would just declare the move operations explicitly defaulted:
class VideoSender {
public:
VideoSender() = default;
~VideoSender() {
// a moved thread is not joinable
if (encoderThread.joinable()) { encoderThread.join(); }
}
VideoSender(const VideoSender&) = delete;
VideoSender& operator=(const VideoSender&) = delete;
// Move constructor and move assignment operator
// Transfer ownership of the thread to this object
VideoSender(VideoSender&&) noexcept = default;
VideoSender& operator=(VideoSender&&) noexcept = default;
private:
// Brace initializer
std::thread encoderThread{ []{} };
};
For the RemoteCom I would just refer to the rule of zero (C++ Core Guidelines C.20):
class RemoteCom {
// Implicitly declared special member functions are all ok
private:
VideoSender videoSender;
};
With the declarations above the following code would compile on C++14 and C++11:
#include <utility>
// Move construction (may be elided)
RemoteCom com = FunctionReturningARemoteCom();
// Move assignment operator
com = FunctionReturningARemoteCom();
// Move construction
Remote com2 = std::move(com);
With C++17 things are a little bit different because of something called guaranteed copy elision, but that is outside of this answer.
This question already has answers here:
Object array initialization without default constructor
(14 answers)
Closed 2 years ago.
Let's say I have a class A :
class A{
public:
A(int const& someValue, std::string const& anotherOne);
private:
std::string m_string_member;
int m_int_member;
};
And I want to allocate an array of this class using new :
A* myClassArray = new A[69];
I get the error : No default constructor available.
Do I have to write a default constructor for every class I want to use by calling new ?
Short answer: Yes.
Long answer: Lets start with this matrix here https://foonathan.net/images/special-member-functions.png. You provide a constructor which is not the default constructor (yours takes arguments). So the compiler won't automagically generate a default constructor for you. However, in your allocation, you ask the compiler to default construct 69 elements. How should the compiler do this? But, solving this issue is rather easy. Just provide the default constructor, or, even easier, use = default. The latter only works because all your members are default-constructible.
In c++ if no user-declared constructors of any kind are provided for a class type the compiler will always declare a default constructor. If you provide any constructor and want default constructor as well, you should define default constructor explicitly.
This question already has an answer here:
In C++, is a constructor with only default arguments a default constructor?
(1 answer)
Closed 4 years ago.
Does the following one-parameter constructor also serve as a default constructor?
class SomeClass
{
public:
SomeClass(const int &a = 4);
}
(Assuming the constructor is well defined etc.)
Thanks!
Yes, the definition of default constructor allows parameters as long as they have default values:
A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters).
(from the C++1z draft)
Older phrasing:
A default constructor for a class X is a constructor of class X that can be called without an argument.
In addition, your copy constructor will be implicitly defined as defaulted, because you haven't declared one.
There is no such thing as a "default copy constructor". But "default constructor" and "defaulted copy constructor" are meaningful.
This question already has answers here:
When do we need to have a default constructor?
(7 answers)
Closed 8 years ago.
I have the following classes:
class ArithmeticExpression
{
public:
ArithmeticExpression(std::string expr);
}
class Command
{
public:
Command(){};
//this is a virtual class
}
class CommandAssign : public Command
{
private:
ArithmeticExpression expr;
public:
CommandAssign();
CommandAssign(ArithmeticExpression);
}
Now when I try to write the constructor for the CommandAssign class as in:
CommandAssign::CommandAssign(ArithmeticExpression expr)
:Command()
{
this -> expr = ArithmeticExpression(expr.getExpr());
}
I get the error:
no matching function for call to ‘ArithmeticExpression::ArithmeticExpression()’
:Command()
Apparently I can fix that by adding an empty constructor in ArithmeticExpression class that does not do anything. What is it so special about this empty constructor that makes it work? I do not explicitly call anywhere. Do you always need to define an empty constructor in C++?
I wanted to emphasize that although from the title it seems that my question is similar to the one some users suggested as being a duplicate of, the answer I was looking for is NOT there. I was simply trying to understand what happens when a constructor is called and how to avoid defining a useless default constructor, which I knew already is not automatically defined by the compiler in the case where I define one with parameters.
A default constructor will only be automatically generated by the compiler if no other constructors are defined.
EDIT:
The default constructor is needed for object initialization.
All members are initialised before the constructor body begins. If one doesn't have an entry in the initialiser list, then it will be default-initialised; but this is only possible (for a class type) if it has a default constructor.
expr is not initialised in the initialiser list, and doesn't have a default constructor (since declaring any constructor prevents one from being implicitly generated), so it can't be initialised - hence the error.
You should initialise it in the list, rather than reassigning it in the constructor body:
CommandAssign::CommandAssign(ArithmeticExpression expr) :
expr(expr.getExpr())
{}
Note that there's no need to explicitly default-construct the Command sub-object. This also requires the constructor of ArithmeticExpression to be public: it's private in your example code.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Trouble with inheritance of operator= in C++
hello everyone, let's assume I have two classes:
Base{}; //inside I have operator=
Derived{}; //inside I don't have operator=
why this one is working perfectly:
Derived der1, der2;
der1=der2; //<-here I know that it actually calls my Base::operator=
and this one is not:
Derived der1;
Base bas1;
der1=bas1; //<-here why can't call Base::operator=?
The implicitly declared copy assignment operator looks like
Derived& operator=(const Derived&);
This implicitly declared function calls operator= for each base class and member subobject (this is why the Base class operator= overload is called).
bas1 is of type Base, not Derived, and there is no implicit conversion from Base to Derived, hence it doesn't work. You would need to declare an appropriate assignment operator in order to support assigning an object of type Base to an object of type Derived (this would be a bit unusual though).
That's because
Derived& Derived::operator=(Derived const&);
hides the assignment
Base& Base::operator=(Base const&);
from the base class. This has something to do with name lookup and scopes. Check your favorite C++ book on hiding.