I've been exploring the possibilities of Move Constructors in C++, and I was wondering what are some ways of taking advantage of this feature in an example such as below. Consider this code:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
// ??? How can we take advantage of move constructors here?
}
// ... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() {
Foo<5> result;
// Do stuff with 'result'
return result;
}
int main() {
Foo<5> foo(bar());
// ...
return 0;
}
In this above example, if we trace the program (with MSVC++ 2011), we see that Foo<N>::Foo(Foo<N>&&) is called when constructing foo, which is the desired behaviour. However, if we didn't have Foo<N>::Foo(Foo<N>&&), Foo<N>::Foo(const Foo<N>&) would be called instead, which would do a redundant copy operation.
My question is, as noted in the code, with this specific example which is using a statically-allocated simple array, is there any way to utilize the move constructor to avoid this redundant copy?
First off, there's a general sort of advice that says you shouldn't write any copy/move constructor, assignment operator or destructor at all if you can help it, and rather compose your class of high-quality components which in turn provide these, allowing the default-generated functions to Do The Right Thing. (The reverse implication is that if you do have to write any one of those, you probably have to write all of them.)
So the question boils down to "which single-responsibility component class can take advantage of move semantics?" The general answer is: Anything that manages a resource. The point is that the move constructor/assigner will just reseat the resource to the new object and invalidate the old one, thus avoiding the (presumed expensive or impossible) new allocation and deep copying of the resource.
The prime example is anything that manages dynamic memory, where the move operation simply copies the pointer and sets the old object's pointer to zero (so the old object's destructor does nothing). Here's a naive example:
class MySpace
{
void * addr;
std::size_t len;
public:
explicit MySpace(std::size_t n) : addr(::operator new(n)), len(n) { }
~MySpace() { ::operator delete(addr); }
MySpace(const MySpace & rhs) : addr(::operator new(rhs.len)), len(rhs.len)
{ /* copy memory */ }
MySpace(MySpace && rhs) : addr(rhs.addr), len(rhs.len)
{ rhs.len = 0; rhs.addr = 0; }
// ditto for assignment
};
The key is that any copy/move constructor will do a full copying of the member variables; it is only when those variables are themselves handles or pointers to resources that you can avoid copying the resource, because of the agreement that a moved object is no longer considered valid and that you're free to steal from it. If there's nothing to steal, then there's no benefit in moving.
In this case it's not useful because int has no move-constructors.
However, it could be useful if those were strings instead, for example:
template<unsigned int N>
class Foo {
public:
// [snip]
Foo(Foo<N>&& other) {
// move each element from other._nums to _nums
std::move(std::begin(other._nums), std::end(other._nums), &_nums[0]);
}
// [snip]
private:
std::string _nums[N];
};
Now you avoid copying strings where a move will do. I'm not sure if a conforming C++11 compiler will generate equivalent code if you omit all the copy-/move-constructors completely, sorry.
(In other words, I'm not sure if std::move is specially defined to do an element-wise move for arrays.)
For the class template you wrote, there's no advantage to take in a move constructor.
There would be an advantage if the member array was allocated dynamically. But with a plain array as a member, there's nothing to optimize, you can only copy the values. There's no way to move them.
Usually, move-semantic is implemented when your class manages resource. Since in your case, the class doesn't manages resource, the move-semantic would be more like copy-semantic, as there is nothing to be moved.
To better understand when move-semantic becomes necessary, consider making _nums a pointer, instead of an array:
template<unsigned int N>
class Foo {
public:
Foo()
{
_nums = new int[N](); //allocate and zeo-initialized
}
Foo(const Foo<N>& other)
{
_nums = new int[N];
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other)
{
_nums = other._nums; //move the resource
other._nums=0; //make it null
}
Foo<N> operator=(const Foo<N> & other); //implement it!
virtual ~Foo() { delete [] _nums; }
private:
int *_nums;
};
Related
So, for instance, I have the following code which I want a object's pointer
member to point to a memory which was pointed by another temporary object's
member.
struct A {
int * vals;
A(): vals(new int[10]) { }
~A(){ delete[] vals; }
};
int main() {
A a;
{
A temp;
for (int i = 0; i < 10; ++i) {
temp.vals[i] = 100;
}
a.vals = temp.vals;
temp.vals = nullptr; // avoid double free
}
I set temp.vals to nullptr in case the destructor of temp will free that
memory. So far so good, I guess. However, if I change the vals to a dynamic
array, i.e. a pointer to pointers:
struct A {
int ** vals;
A(): vals(new int*[10]) {
for (int i = 0; i < 10; ++i) {
vals[i] = new int;
}
}
~A(){
for (int i = 0; i < 10; ++i) {
delete vals[i]; // illegal to dereference nullptr
}
delete [] vals;
}
};
int main() {
A a;
{
A temp;
for (int i = 0; i < 10; ++i) {
temp.vals[i] = new int(1);
}
a.vals = temp.vals;
temp.vals = nullptr; // avoid double free
}
}
I have add a for loop in destructor to handle the nested allocated memory, and
to avoid the memory be freed by the destructor of temp, I set temp.vals to
nullptr, which, however will cause a segmentation fault since when destructor
of temp is called, it is illegal to dereference a nullptr.
So my question is, how to correct set the destructor to handle the dynamic array.
I'm not a native speaker, so please forgive my grammar mistakes.
The typical C++ solution looks a bit different:
class A {
private:
int* vals;
public:
A(): vals(new int[10]) { }
~A(){ delete[] vals; }
A (A const& src); // Copy constructor
A (A&& src) : vals (src.vals) { src.vals = nullptr; }
A& operator=(A const&); // Assignment
A& operator=(A &&);
};
You can now write a = std::move(temp). Outside the class, you don't need to know how the inside works.
For your 2D array, just define the same special member functions. This is usually called the "Rule of Five". If you need a destructor, you probably need the other 4 functions as well. The alternative is the "Rule of Zero". Use std::vector or another class that manages memory for you.
However, if I change the vals to a dynamic array, i.e. a pointer to pointers
In the first program, vals is a pointer. It points to a dynamic array of integers. In the second program, vals is also a pointer. It points to a dynamic array of pointers.
how to correct set the destructor to handle the dynamic array.
You set vals to null. If null is a valid state for vals, then it isn't correct to unconditionally indirect through it in the destructor. You can use a conditional statement to do so only when vals isn't null.
However, the program is hardly safe because vals is public, and thus it is easy to mistakenly write a program where it is assigned to point to memory that isn't owned by the object. In cases where destructor cleans up an owned resource, it is important to encapsulate the resource using private access to prevent accidental violation of class invariants that are necessary to correctly handle the resource.
Now that vals is no longer outside of member functions, you cannot transfer the ownership like you did in your example. The correct way to transfer the ownership is to use move assignment (or constructor). The implicitly generated move constructor cannot handle an owning bare pointer correctly. You must implement them, as well as the copy assignment and constructor.
Furthermore, you should use an owning bare pointer in the first place. You should use a smart pointer instead. If you simply replaced the bare pointers with unique pointer, then the implicitly generated move assignment and constructor would handle the resource correctly, and the copy assignment and constructor would be implicitly deleted.
Lastly, the standard library has a container for dynamic arrays. Its called std::vector. There's typically no need to attempt to re-implement it. So in conclusion, I recommend following:
std::vector<int> a;
{
std::vector<int> temp;
for (int i = 0; i < 10; ++i) {
temp.vals[i] = 1;
}
a = std::move(temp);
}
There are still issues such as the temporary variable being entirely unnecessary, and the loop could be replaced with a standard algorithm, but I tried to keep it close to the original for the sake of comparison.
P.S. It's pretty much never useful to dynamically allocate individual integers.
Lets assume I am trying to create "immutable" class objects (i.e. members variables are defined with const). So when calling the constructor I currently call separate init functions to initialise the class members. But as a result there seems to be a lot of new vector-creating & vector-copying going on.
If the members weren't const I could perform the initialisations in the { } section of the constructor and write directly into values (which I assume would be more efficient). But this is not possible.
Are there better/cleaner/more efficient ways to design the construction of immutable classes?
#include <vector>
class Data
{
public:
const std::vector<int> values;
Data(unsigned int size, int other) : values(init(size, other)) { }
Data(const std::vector<int>& other) : values(init(other)) { }
private:
std::vector<int> init(unsigned int size, int other) {
std::vector<int> myVector(size);
for (unsigned int i = 0; i < size; ++i)
myVector[i] = other * i;
return myVector;
}
std::vector<int> init(const std::vector<int>& other) {
std::vector<int> myVector(other);
for (unsigned int i = 0; i < other.size(); ++i)
myVector[i] *= myVector[i] - 1;
return myVector;
}
};
int main() {
Data myData1(5, 3); // gives {0, 3, 6, 9, 12}
Data myData2({2, 5, 9}); // gives {2, 20, 72}
return 0;
}
Your current design is perfectly fine. The initialization takes place in the constructor's member initialization list, so it will trigger a move at worst (which is quite cheap for a vector anyway) and NRVO at best.
NRVO is Named Return Value Optimization. When a function returns a named variable with automatic storage duration, the compiler is allowed to elide the copy/move. Note that however, copy/move constructors still need to be available even in the case of an elision. Here is a dummy example to sum up that concept:
SomeType foo() { // Return by value, no ref
SomeType some_var = ...; // some_var is a named variable
// with automatic storage duration
do_stuff_with(var);
return some_var; // NRVO can happen
}
(Your init function follows that pattern.)
In C++17 you could even benefit from a guaranteed copy elision in that scenario depending on the shape of your init function. You can find out more about this in this other SO answer.
Note: Since you tagged your question c++11 I assume move semantics are available.
You say
there seems to be a lot of new vector-creating & vector-copying going on.
But I am unsure of it. I would instead expect one full creation and one move here:
init builds and returns a temporary vector (ok full vector creation, directly with the final size) which is used to initialize the const member (ok a move should occur here). We should control the generated assembly here, but a decent compiler should build the data block once, and move it into the data member.
So unless you can prove by profiling (or by looking at the assembly generated by your compiler) that things really need to be optimized here, I would gladly keep on with this code because it clearly declares the member constness.
The solution here is to remove const from the member vector so that you can perform your initialisation in place, rather than by copying.
If you want values to be readable but not writable by users of the class, you can expose a const reference to it:
class Data {
std::vector<int> values_;
// constructors...
public:
std::vector<int> const& values() const { return values_; }
};
I am new to C++ and I do not know how to solve the following problem.
The class Foo has a constructor which creates a array of doubles of a given size. The destructor deletes this array. The print method prints the array.
#include <iostream>
class Foo {
private:
int size;
double* d;
public:
Foo(int size);
~Foo();
void print();
};
Foo::Foo(int size)
{
this->size = size;
d = new double[size];
for (int i = 0; i < size; i++)
{
d[i] = size * i;
}
}
Foo::~Foo()
{
delete[] d;
}
void Foo::print()
{
for (int i = 0; i < size; i++)
{
std::cout << d[i] << " ";
}
std::cout << std::endl;
}
Now I have a function func(Foo f) which does nothing.
void func(Foo f){}
int main()
{
Foo f(3);
f.print();
func(f);
Foo g(5);
f.print();
return 0;
}
Executing this code gives the following output:
0 3 6
0 5 10
Although I am printing f both times, somehow the values inside the array have changed.
I guess that the destructor of Foo is called on parameter Foo f after the execution of func(Foo f) and this frees the allocated memory for d, which is reallocated for Foo g(5). But how can I avoid this without using vectors or smart pointers?
The problem is with the design of the class. The default copy constructor will create a new instance of Foo when passed by value into the free standing function named func.
When the instance of Foo named f exits scope then the code invokes the user-provided destructor that deletes the array of doubles. This opens the code to the unfortunate situation of deleting the same array twice when the original instance of Foo named f exits scope at the end of the program.
When run on my machine, the code does not produce the same output. Instead I see two output lines of 0 3 6 followed by fault indicating the double free operation.
The solution is to avoid the copy by passing by reference (or by const reference): void func(Foo const &f) { } or to supply a valid copy constructor that makes a deep copy of the underlying array. Passing by reference is just a bandaid that avoids exercising the bug.
Using std::vector<double> fixes the problem because the default copy constructor will perform a deep copy and avoid double deallocation. This is absolutely the best approach in this small example, but it avoids having to understand the root of the problem. Most C++ developers will learn these techniques then promptly do what they can to avoid having to write code that manually allocates and deallocates memory.
You should probably pass the object as a reference func(Foo& f) or - if you do not want to modify it at all - as a constant reference func(const Foo& f). This will not create or delete any objects during the function call.
Aside from that, as others have already mentioned, your class should better implement the Rule of Three.
When you pass a value to a function, it is supposed to be copied. The destructor is run on the copy and should no effect on the original object. Foo fails to implement a copy constructor, so compiler provides the default one which simply performs a member-wise copy of the struct. As a result, the "copy" of Foo inside Func contains the same pointer as the original, and its destructor frees the data pointed to by both.
In order to be usable by idiomatic C++ code, Foo must implement at least a copy constructor and an assignment operator in addition to the destructor. The rule that these three come together is sometimes referred to as "the rule of three", and is mentioned in other answers.
Here is an (untested) example of what the constructors could look like:
Foo::Foo(const Foo& other) {
// copy constructor: construct Foo given another Foo
size = other->size;
d = new double[size];
std::copy(other->d, other->d + size, d);
}
Foo& Foo::operator=(const Foo& other) {
// assignment: reinitialize Foo with another Foo
if (this != &other) {
delete d;
size = other->size;
d = new double[size];
std::copy(other->d, other->d + size, d);
}
return *this;
}
Additionally, you can also modify functions like func to accept a reference to Foo or a constant reference to Foo to avoid unnecessary copying. Doing this alone would also happen fix the immediate problem you are having, but it would not help other issues, so you should definitely implement a proper copy constructor before doing anything else.
It's a good idea to get a good book on C++ where the rule of three and other C++ pitfalls are explained. Also, look into using STL containers such as std::vector as members. Since they implement the rule of three themselves, your class wouldn't need to.
One problem is that calling func creates a bitwise copy. When that copy goes out of scope the destructor is called which deletes your array.
You should change void func(Foo f){} to void func(Foo& f){}.
But better yet you add a create copy constructor or add a private declaration to stop it being called unexpectedly.
I'm new to C++ and am new to using RAII for deleting allocated memory. I wrote this code as a sample of what it would take to automatically allocate and later delete a character array. I know there's a string class out there, but thought I'd start with the older stuff first. Does this sample look correct? And is it the way others would create a string and delete it automatically?
#include <iostream>
using namespace std;
class StringGetter
{
private:
char* theString;
public:
StringGetter(char* name)
{
this->theString = new char[1024];
strcpy_s(this->theString, strlen(name) + 1, name);
}
char* GetString()
{
return this->theString;
}
~StringGetter()
{
delete[] this->theString;
}
};
int main()
{
char* response;
{
StringGetter getter("testing");
response = getter.GetString();
}
cin.get(); // pauses the console window
}
It looks like you get the main idea, but there's a couple things worth mentioning.
1) As #chris mentioned, you're forgetting your copy constructor, copy assignment operator, move constructor, and move assignment operator. Copy should be either manually written or disabled, move can be defaulted. (aka You've not followed the rule of 5)
2) Prefer to use std::unique_ptr to represent ownership. It's already done all of the hard work for you. By keeping your wrapped string in a std::unique_ptr the default versions of the copy/move special functions will preserve correctness (though you'll still want to implement the copy operations if you want them to be enabled).
Here's what this might look like:
class StringGetter {
public:
explicit StringGetter(char* name) {
strSize = strlen(name);
str = std::unique_ptr<char[]>(new char(strSize+1));
std::copy_n(name, strSize + 1, str.get());
}
StringGetter(const StringGetter& other) {
strSize = other.strSize;
str = std::unique_ptr<char[]>(new char(strSize+1));
std::copy_n(other.str.get(), strSize + 1, str.get());
}
StringGetter(StringGetter&& other) = default;
StringGetter& operator=(const StringGetter& rhs) {
auto temp = rhs;
swap(temp);
return *this;
}
StringGetter& operator=(StringGetter&& rhs) = default;
const char* getString() const noexcept {
return str.get();
}
void swap(StringGetter& other) {
std::swap(str, other.str);
std::swap(strSize, other.strSize);
}
private:
std::unique_ptr<char[]> str;
int strSize;
};
Miscellaneous items:
1) Note that std::unique_ptr handles the RAII. When I replace 'str' in the copy constructor, it deletes the old string automatically.
2) I size the dynamically allocated memory to match the input string. This prevents overflows/wasted memory.
3) The constructor is explicit. This prevents undesirable conversions. Rule of thumb is to use the explicit keyword on all single argument constructors.
4) I made getString constant so that you can still call it on const instances of the class.
5) I replaced the str-family copy function with std::copy_n. It's more general and can avoid certain pitfalls in obscure cases.
6) I used the copy-swap idiom in the copy assignment operator. This promotes code reuse/avoids duplication.
7) When C++14 comes out, replace the std::unique_ptr constructor call with std::make_unique for added exception-safety and to remove redundancy.
Here is an attempt at an RAII class that does something similar:
template<std::size_t N>
class StringGetter_N
{
private:
std::unique_ptr<char[]> buffer;
public:
StringGetter_N()
{
buffer.reset( new char[N] );
buffer.get()[0] = 0;
}
explicit StringGetter_N(char const* name)
{
buffer.reset( new char[N] );
strcpy_s(buffer.get(), N-1, name);
buffer.get()[N-1] = 0; // always null terminate
}
StringGetter_N( StringGetter_N&& other ) = default;
char* GetString()
{
return buffer.get();
}
};
class StringGetter : StringGetter_N<1024> {
explicit StringGetter( const char* name ):StringGetter_N<1024>(name) {}
StringGetter():StringGetter_N<1024>() {}
};
notice that I delegated the resource management to a smart pointer. Single responsibility principle means that the resource management object (like a smart pointer) can do just that, and if you want to write a class that represents a heap-allocated buffer of fixed size, you delegate that sub problem to the smart pointer, and just manage it in your class.
As it happens, std::unique_ptr properly implements
But really, it is usually much simpler to just use a std::vector, as you can usually determine how much space you need at run-time before needing a buffer to write to.
If you do implement your own RAII class, you should follow these rules:
Single argument constructors that are not copy/move constructors should usually be explicit.
If you implement a non-trivial destructor, you must (implement or block usage of) (copy and/or move constructor) and (copy and/or move operator=). This is known as the rule of 3 (or rule of 5 in C++11).
Your RAII class should do little except manage the resource. If you want to do something else, use an RAII class to manage the resource, then store it within another class that does the fancy extra work.
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class myClass{
public:
int *num1;
myClass();
};
myClass::myClass(){
num1 = new int[1];
num1[0] = 10;
}
int main()
{
myClass *myclass;
myclass = new myClass[10];
cout << myclass[0].num1[0] << endl;
delete &myclass[0];
cout << myclass[0].num1[0] << endl;
}
I want to delete the first instance of myclass (myclass[0]).
This code does not run correctly, it fails during the delete part. There is probably something I am missing.
What did I do wrong?
You cannot delete just a portion of an array created with new. new allocates a block of memory which can only be deleteed all together.
If you want an object to free its own internal data you'll have to arrange for the class, which should encapsulate and hide its own internal resources, to do that itself.
If you want a smaller block of memory holding the array you allocated, then you must allocate a smaller block and move the contents that you wish to keep into the new block, and then delete the entire old block:
int *arr = new int[10];
int *tmp = new int[9];
std::copy(arr+1, arr+10, tmp);
delete [] arr;
arr = tmp;
You need to design your class to manage its own resources, and to handle copying or moving. Your current myClass allocates an array but relies on other code to handle cleaning up. This is not a good way to go about doing this, because often no other code is in a good position to do the correct thing, and even when you could you'll very frequently make mistakes.
Since you're allocating in the constructor you need a destructor that handles deallocation. And then since you implement one of three special operations (copy-ctor, copy-assignment, destructor) you need to consider implementing them all. (This is called 'The Rule of Three'. In C++11 it becomes 'The Rule of Five' with the addition of move-ctors and move assignment.)
class myClass {
public:
myClass();
// destructor to handle destroying internal resources correctly
~myClass();
// copy constructor and copy assignment operator, to handle copying correctly
myClass(myClass const &rhs);
myClass &operator=(myClass const &rhs);
// move constructor and move assignment operator, to handle moves correctly (C++11)
myClass(myClass && rhs);
myClass &operator= (myClass &&rhs);
private:
int *num1; // private so external code can't screw it up
public:
// limited access to num1
int size() const { if (num1) return 1; else return 0; }
int &operator[] (size_t i) { return num1[i]; }
};
You can implement the constructor just as you did, or you could use the initializer list and C++11 uniform initialization:
myClass::myClass() : num1(new int[1]{10}) {}
Now, the destructor you want depends on the semantics you want the class to have, and the particular invariants you want to maintain. 'value' semantics are the norm in C++ (if you're familiar with Java or C# those languages encourage or require 'reference' semantics for user defined types). Here's a destructor you might use if you want value semantics, and if you maintain an invariant that num1 always owns memory or is null.
myClass::~myClass() { delete num1; }
Copying and moving can be handled in different ways. If you want to disallow them entirely you can say (in C++11):
myClass::myClass(myClass const &rhs) = delete;
myClass &myClass::operator=(myClass const &rhs) = delete;
myClass::myClass(myClass && rhs) = delete;
myClass &myClass::operator= (myClass &&rhs) = delete;
Or if you want to allow copying and or moving (and maintain value semantics and the invariant mentioned above) then you can implement either or both of these pairs of functions:
myClass::myClass(myClass const &rhs) : num1( rhs.size() ? new int[1]{rhs[0]} : nullptr) {}
myClass &myClass::operator=(myClass const &rhs) {
if (num1)
num1[0] = rhs[0];
}
myClass::myClass(myClass && rhs) : num1(rhs.num1) { rhs.num1 = nullptr; } // remember to maintain the invariant that num1 owns the thing it points at, and since raw pointers don't handle shared ownership only one thing can own the int, and therefore only one myClass may point at it. rhs.num1 must be made to point at something else...
myClass &myClass::operator= (myClass &&rhs) { std::swap(num1, rhs.num1); } // steal rhs.num1 and leave it to rhs to destroy our own num1 if necessary. We could also destroy it ourselves if we wanted to.
With this implementation you can now treat a myClass object the same as you would an int or any other 'value' type. You no longer need to worry about managing its internal resources; it will take care of them itself.
int main() {
std::vector<myClass> myclassvec(10);
cout << myclassvec[0][0] << '\n';
myclassvec.erase(myclassvec.begin()); // erase the first element
cout << myclassvec[0][0] << '\n'; // access the new first element (previously the second element);
}
Create a function inside of your class the handles the deletion of its private members, maybe called FreeMem(int index)
void myClass::FreeMem()
{
delete [] num1
}
But honestly, freeing memory of an object without the use of a destructor in this sort of a program is hazardous and downright bad practice. I would recommend freeing the memory in your destructor, so when the object terminates it frees the memory,
myClass::~myClass()
{
delete [] num1;
}
Another thing to note on, if you're only creating one value in your dynamic variable, it would be easier to write it as:
int * pnum = new int;
//or in your class..
pnum = new int;
among other things, you have a lot of flaws in your program. I would recommend re-reading up on classes again.