How do I make this C++ object non-copyable?
class Foo {
private:
Foo();
Foo( const Foo& ); // non construction-copyable
Foo& operator=( const Foo& ); // non copyable
public:
static Foo* create();
}
If you're using boost, you can also inherit from noncopyable : http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp
EDIT: C++11 version if you have a compiler supporting this feature:
class Foo {
private:
Foo();
public:
Foo( const Foo& ) = delete; // non construction-copyable
Foo& operator=( const Foo& ) = delete; // non copyable
static Foo* create();
}
Note that deleted methods should be public: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete
Make a class non-copyable *and* non-movable
As others already mentioned in the comments, deleted constructors was introduced in C++11. To answer your question, the following rules hold in general:
- The two copy operations are independent. Declaring copy constructor does not prevent compiler to generate copy assignment and vice versa. (Same as in C++98)
- Move operations are not independent. Declaring either one of them prevents the compiler to generate the other. (Different from copy operations.)
- If any of the copy operations is declared, then none of the move operation will be generated. (Your case.)
- If any of the move operation is declared, then none of the copy operation will be generated. This is the opposite rule of the previous.
- If a destructor is declared, then none of the move operation will be generated. Copy operations are still generated for reverse compatibility with C++98.
- Default constructor generated only when no constructor is declared. (Same as in C++98)
As requested in the comments, here are some sources (C++11 is draft N3242):
- Copy operations: § 12.8.8, § 12.8.19
- Move operations: § 12.8.10, § 12.8.21
- Default constructor: § 12.1.5
Can a non-copyable member be used as alternative to make an object non-copyable?
Since C++11, the proper idiom for making a class non-copyable is to = delete
the copy constructor/assignment operator. That's what C++ programmers are told to do, and that's what other C++ programmers will expect to see when looking for that behavior in your class..
It's fine to have a subobject (member or base class) that is non-copyable, and thus your default copy constructor/assignment operator will be implicitly deleted. But you should only do this for a subobject that happens to be non-copyable. That is, you have a unique_ptr<T>
or mutex
or whatever as a member because you need a unique_ptr<T>
or a mutex
as class instance data. Not because you're using it as a hack to make the type non-copyable.
The downsides of using a member subobject for this purpose are:
It muddles the meaning of your code. Your
mutex _dummy;
example tells me that your type has amutex
in it. If nothing ever uses that variable, then that tells me that your code is rather incoherent; if you don't need a subobject, you don't declare one.= delete
is the proper idiom, so it is what you should use.boost::noncopyable
was the C++98/03 idiom because it was an empty class. And thus, common empty base optimization would ensure that it wouldn't take up any space in the derived class. Empty members get no such optimization, so a memberboost::noncopyable
will always make your class bigger, to no advantage. And while you could point to the upcoming C++20[[no_unique_address]]
attribute, see reason #1.
how to initialize a non copyable object data member
To make the above compile:
Add the headers:
#include <string>
#include <memory>
You also need to be able to construct the A
so you need to make the constructors public:
class A //abstract class
{
public: // Added this:
A() = default;
.....
};
Your main issue is here in making the shared object.
obj2(std::make_shared<SI::Z>(SI::Z(p,"hi")))
You don't need to constructed the SI::Z
object here (as it is not copyable this is an issue). What you want to do is pass the arguments that will be used to create the SI::Z
object. Then std::make_shared()
will call new and forward these parameters to the constructor.
obj2(std::make_shared<SI::Z>(p, "hi")) // Notice the diff?
Non-copyable struct in C?
You can do this using opaque pointers. The idea is:
- You define a struct somewhere and you define all of its operations in terms of a pointer to that struct. That would probably be a standalone compilation unit.
- The consumers of your struct only get a declaration but not the full definition of that struct, which means that they don't know the layout or even the size of the struct. It follows that they are able to receive, store, and pass around any pointers to that struct, but not values of it.
How to handle classes that are not copyable?
Moveable types
You can make the class moveable by adding the move constructor and move assignment operator. (Some possibly useful overview of that.)
...
// rough sketch
// Having the path as `char*` seems
// bad (use std::string instead),
// but let's stick with the example as posted)
File(File&& other)
: path(nullptr)
, cfile(nullptr)
{
using std::swap;
// steal the guts of the moved-from object
swap(path, other.path);
swap(cfile, other.cfile);
}
The move assignment operator can be a little bit more tricky, what with self-assigment checks.
/or/
Smart pointers
You can wrap instances of these classes in a smart pointer and work with those:
std::shared_ptr
,std::unique_ptr
etc.
std::unique_ptr<File> Search(const char* filepath) {
auto pfile = std::make_unique<File>(filepath);
...
return pfile;
}
This is especially helpful when you work with 3rd party classes (possibly legacy) that don't support move operations.
Yes, these have heap allocation overhead, but given the overhead of opening e.g. a file or acquiring another expensive resource that prevents copying, the heap allocation overhead might well be negligible.
Is it possible to make an noncopyable type in C#
It is default behavior. If you have class:
class foo {
public string bar { get; set; }
}
and somewhere you do this:
foo f1 = new foo();
foo f2 = f1;
Both f1
and f2
will reference same instance. If you, for example, set f1.bar = "bar"
, value read from f2.bar
will be "bar"
.
Returning non-copyable non-movable object with explicit constructor
No, this isn't possible. There is no mechanism to call explicit constructors while returning from a function in C++11 or 14 without having an implicit move or copy (that the compiler will certainly elide).
In C++17 you can just type return NonCop(1,2);
and due to "guaranteed elision" it will no longer require a move or copy constructor.
But this is C++, so yes, I can make your code work with zero additional overhead. By cheating, and returning a different type.
template<class T>
struct implicit_construct:T {
template<class...Ts>
implicit_construct(Ts&&...ts):
T(std::forward<Ts>(ts)...) // note: this is an EXPLICIT construction
{}
};
implicit_construct<NonCop> get_non_cop()
{
return {1, 2};
}
Live example.
An implicit_construct<NonCop>
derives from a NonCop
, so you can store the return value in a NonCop&&
.
If you are writing NonCop
yourself, then what I'd do is add:
struct explicit_construct_t {};
// ...
struct NonCop {
// ...
template<class...Ts>
NonCop( explicit_construct_t, Ts&&...ts ):
NonCop( std::forward<Ts>(ts)... )
{}
// ...
};
which means you can call explicit constructors by prefixing it with a explicit_construct_t
to call them implicitly:
NonCop get_non_cop() {
return {explicit_construct_t{}, 1, 2};
}
Related Topics
Visual Studio Code Formatting for "{ }"
Is There Any Reason to Use the 'Auto' Keyword in C++03
What Is the Underlying Data Structure of a Stl Set in C++
Launch Failed. Binary Not Found. Cdt on Eclipse Helios
Reinterpret_Cast VS. C-Style Cast
Do All Pointers Have the Same Size in C++
Can Std::Begin Work with Array Parameters and If So, How
Efficient Bitwise Operations for Counting Bits or Find the Right|Left Most Ones
Why Is Iterating Though 'Std::Vector' Faster Than Iterating Though 'Std::Array'
Why Is the Empty Base Class Optimization (Ebo) Is Not Working in Msvc
How to Use Doxygen to Create Uml Class Diagrams from C++ Source
When Should I Use Typedef in C++
Conversion Function for Error Checking Considered Good
Is F(Void) Deprecated in Modern C and C++
Compute Median of Values Stored in Vector - C++
Most Efficient/Elegant Way to Clip a Number
Virtual Tables and Memory Layout in Multiple Virtual Inheritance