Explicitly declare defaulted methods in C++ [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
According to C++11 standard you can declare special member functions as defaulted using default keyword.
class Foo
{
public:
Foo() = default;
Foo(const Foo& source) = default;
Foo(Foo&& source) = default;
~Foo() = default;
Foo& operator=(const Foo& right) = default;
Foo& operator=(Foo&& right) = default;
};
I was wondering is it a good practice to declare all those methods explicitly defaulted or deleted if you don't need custom implementation of them. For example, I need to implement copy constructor and copy-assignment operator for my class. Should I mark all other special member function with default or delete keywords in order to not think each time I look at a class which are provided by compiler and which are not?

It depends. There are rules to when and whether the compiler will generate those functions automatically. In cases when the compiler wont do that and you need them, you could force it to generate them by using default or implement it yourself. The cases when the compiler wont generate functions are (this is not the full list, please refer to you're compiler's documentation):
no default constructor is generated when a constructor with arguments is declared
no move constructor and move assignment operator is generated when you declare copy constructor and copy assignment operator (and visa-versa)
So, in those cases you might want to bring them back by using default if you know that they'll be needed somewhere. In most cases, however, you should let the compiler do its thing. You'll get an error if one of those functions is not implemented automatically.
P.S. Visual studio does not yet support default and delete for move constructor and move assignment operator, yet.

Related

Difference between default copy constructor vs no copy constructor [duplicate]

This question already has answers here:
Defaulted constructor vs implicit constructor
(2 answers)
What is the difference between constructor "=default" and the compiler generated constructor in C++?
(3 answers)
Closed 4 months ago.
In C++, is there a difference between declaring a copy constructor default as opposed to not declaring one at all? For visualization:
class A{
int x;
}
vs
class B{
int x;
B() = default;
B(const B&) = default;
}
How about default copy assignment, default move constructor, and default move assignment? If I'm just going to declare them as default, could I just as well not declare them at all?
I looked on the internet and haven't been able to find an answer

Call to implicitly deleted copy constructor of class error [closed]

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.

Unable to understand error messege raised by compiler on copy constructor [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
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.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
#include <iostream>
using namespace std;
class dummy
{
private:
int a,b,*p;
public:
void setdata(int x,int y,int z)
{
a=x;
b=y;
p=&z;
}
void showdata()
{
cout<<"a "<<a<<"b "<<b<<" pointer address c "<<&p<<endl;
}
dummy(dummy &d)
{
a=d.a;
b=d.b;
p=d.p;
cout<<"a "<<a<<"b "<<b<<" pointer address c "<<&p<<endl;
}
dummy(dummy &d)
{
d.a;b=d.b;p=d.p;
}
};
int main()
{
dummy d1;//error is here;
d1.setdata(3,4,5);
dummy d2=d1;
d2.showdata();
d1.showdata();
return 0;
}
raised error
:/root/copy deep shallow/main.cpp|15|error: no matching function for call to ‘dummy::dummy()’|
I am unable to understand why the error messege is raised and what is the solution for this issue
The class does not have the default constructor because there is the explicitly defined copy constructor
dummy(dummy &d){a=d.a;b=d.b;p=d.p;}
(that shouuld be declared with the parameter const dummy &)
However in this declaration
dummy d1;
there is needed the default constructor that is absent.
You have explicitly to define the default constructor.
Take into account that for example this member function
void setdata(int x,int y,int z)
{a=x;b=y;p=&z;}
leads to undefined behavior because the pointer p will have an invalid value after exiting the function because the local variable (parameter) z will be destroyed.
dummy()
{
}
dummy(dummy &d)
{
a=d.a;
b=d.b;
p=d.p;
cout<<"a "<<a<<"b "<<b<<" pointer address c "<<&p<<endl;
}
This will fix your issue.
In this way you define a default constructor (1st) and a copy-constructor (2nd)
In your code you provided no default constructor and two copy constructor, so compiler will complain about the absence of constructor first, but when will you'll solve that it will raise another error due to ambiguos copy constructors (compiler will tell you I don't know which one call).
As third error, setData() will lead to undefined behaviour of p being invalid after destruction of z.
Your problem is not with copy-constructor, but with default constructor.
Whenever you write a class in C++, the compiler will generate a set of default functions, so you don't have to type them explicitly. Those are:
Default constructor: dummy::dummy()
Copy constructor: dummy::dummy(const dummy&)
Copy assignment operator: dummy& dummy::operator=(const dummy&)
Destructor: dummy::~dummy()
In C++11 standard you also get move constructor and move assignment operator, but these are not important here.
Compiler adds these to any class for you, but if you define any constructor, it won't generate implicit default constructor.
If you want to have default constructor (and be able to use dummy d1; in code), add the following constructor definition to the class:
dummy(){}
or better, if you use C++11 standard:
dummy() = default;
Side note: you don't need explicit copy constructor in this case. Your implementation simply copies content of every field to new object, and thus implicit copy constructor (generated by compiler) would be enough.

Class default constructor [duplicate]

This question already has answers here:
Two constructors, which is default?
(6 answers)
Closed 8 years ago.
Assuming that we have the class TestClass in our C++ project. A default constructor is the one empty parameters list. So we have:
TestClass();
TestClass(int defaultParam = 0);
Can these two be considered default constructors? And if they can be, is it ethical to have a default constructor like the second line?
Either of
TestClass(void);
TestClass(int defaultParam=0);
can be used as the default constructor. When you have both, it is a problem since the compiler cannot distinguish between the two when the compiler needs to use a default constructor. E.g.
TestClass anObject;
TestClass objectArray[5];
Unrelated to your question
For stylistic reasons, you should use:
TestClass();
instead of
TestClass(void);
The second form is supported by C++ but it's not necessary. The argument type void is necessary only when declaring functions in C.
having more than 1 constructor is called constructor overloading. If there are two default constructors it will generate an error as the compiler will not know which constructor to call while creating the object. If you don't declare a default constructor the complier does it by itself.

C++ OPERATOR EQUAL [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 9 years ago.
Consider the following class definition
class Pumpkin {
public:
Pumpkin(const Pumpkin & other);
~Pumpkin();
// more public member functions
private:
double radius;
// more private member variables
};
Which of the following functions must also be implemented for the Pumpkin class for it to function correctly?
(a) no parameter constructor
(b) operator=
(c) operator() (d) setRadius
(e) operator delete
Which of the following functions must also be implemented for the Pumpkin class for it to function correctly?
Well, of course the ones you declared in the class body. From what you have shown you'll definitely need to define both:
Pumpkin(const Pumpkin & other);
~Pumpkin();
and I don't see any particular reason to follow the Rule of Three, since you have only shown us an harmless double.
But, if you do any RAII or your copy constructor and/or destructor are non-trivial, that's probably the case. In which case you'll have to also define:
Pumpkin& operator=(const Pumpkin&);
and if you are using C++11, it's probably a good idea to define also:
Pumpkin(Pumpkin&&);
Pumpkin& operator=(Pumpkin&&);
namely called move-constructor and move-assignment respectively.