How to create a vector with an initial size by using a custom constructor and without calling the destructor?...
This question already has an answer here:
What is The Rule of Three?
8 answers
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0xn", v.num);
cout << "n---------------n";
cout << "END OF PROGRAM!n";
cout << "---------------nn";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num
at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5));
(This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num
pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int)
function and running it on every single object in the vector? (Of course changing malloc
into realloc
).
c++ class vector
marked as duplicate by Passer By, Baum mit Augen
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 18 at 19:50
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
add a comment |
This question already has an answer here:
What is The Rule of Three?
8 answers
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0xn", v.num);
cout << "n---------------n";
cout << "END OF PROGRAM!n";
cout << "---------------nn";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num
at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5));
(This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num
pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int)
function and running it on every single object in the vector? (Of course changing malloc
into realloc
).
c++ class vector
marked as duplicate by Passer By, Baum mit Augen
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 18 at 19:50
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
2
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
2
Also, in C++ never usemalloc
andfree
, not even for primitive types likeint
arrays. Always begin withstd::vector
. And you need to learn about the rules of three/five/zero, and with astd::vector
you can follow the rule of zero which I recommend.
– Some programmer dude
Nov 11 at 13:42
1
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Usenew
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.
– Jesper Juhl
Nov 11 at 13:45
2
This is only my guess -- There is no need to guess. Thestd::vector
implementation for your compiler is readily available to you by opening up the#include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that thestd::vector
class usesplacement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation ofstd::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.
– PaulMcKenzie
Nov 11 at 14:02
add a comment |
This question already has an answer here:
What is The Rule of Three?
8 answers
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0xn", v.num);
cout << "n---------------n";
cout << "END OF PROGRAM!n";
cout << "---------------nn";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num
at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5));
(This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num
pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int)
function and running it on every single object in the vector? (Of course changing malloc
into realloc
).
c++ class vector
This question already has an answer here:
What is The Rule of Three?
8 answers
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0xn", v.num);
cout << "n---------------n";
cout << "END OF PROGRAM!n";
cout << "---------------nn";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num
at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5));
(This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num
pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int)
function and running it on every single object in the vector? (Of course changing malloc
into realloc
).
This question already has an answer here:
What is The Rule of Three?
8 answers
c++ class vector
c++ class vector
asked Nov 11 at 13:33
Habitate
115
115
marked as duplicate by Passer By, Baum mit Augen
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 18 at 19:50
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by Passer By, Baum mit Augen
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 18 at 19:50
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
2
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
2
Also, in C++ never usemalloc
andfree
, not even for primitive types likeint
arrays. Always begin withstd::vector
. And you need to learn about the rules of three/five/zero, and with astd::vector
you can follow the rule of zero which I recommend.
– Some programmer dude
Nov 11 at 13:42
1
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Usenew
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.
– Jesper Juhl
Nov 11 at 13:45
2
This is only my guess -- There is no need to guess. Thestd::vector
implementation for your compiler is readily available to you by opening up the#include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that thestd::vector
class usesplacement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation ofstd::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.
– PaulMcKenzie
Nov 11 at 14:02
add a comment |
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
2
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
2
Also, in C++ never usemalloc
andfree
, not even for primitive types likeint
arrays. Always begin withstd::vector
. And you need to learn about the rules of three/five/zero, and with astd::vector
you can follow the rule of zero which I recommend.
– Some programmer dude
Nov 11 at 13:42
1
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Usenew
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.
– Jesper Juhl
Nov 11 at 13:45
2
This is only my guess -- There is no need to guess. Thestd::vector
implementation for your compiler is readily available to you by opening up the#include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that thestd::vector
class usesplacement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation ofstd::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.
– PaulMcKenzie
Nov 11 at 14:02
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
2
2
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
2
2
Also, in C++ never use
malloc
and free
, not even for primitive types like int
arrays. Always begin with std::vector
. And you need to learn about the rules of three/five/zero, and with a std::vector
you can follow the rule of zero which I recommend.– Some programmer dude
Nov 11 at 13:42
Also, in C++ never use
malloc
and free
, not even for primitive types like int
arrays. Always begin with std::vector
. And you need to learn about the rules of three/five/zero, and with a std::vector
you can follow the rule of zero which I recommend.– Some programmer dude
Nov 11 at 13:42
1
1
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Use new
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.– Jesper Juhl
Nov 11 at 13:45
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Use new
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.– Jesper Juhl
Nov 11 at 13:45
2
2
This is only my guess -- There is no need to guess. The
std::vector
implementation for your compiler is readily available to you by opening up the #include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that the std::vector
class uses placement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation of std::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.– PaulMcKenzie
Nov 11 at 14:02
This is only my guess -- There is no need to guess. The
std::vector
implementation for your compiler is readily available to you by opening up the #include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that the std::vector
class uses placement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation of std::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.– PaulMcKenzie
Nov 11 at 14:02
add a comment |
2 Answers
2
active
oldest
votes
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), () { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
- Rule of three
- Stop using std::endl
- Why is “using namespace std” considered bad practice?
add a comment |
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), () { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
- Rule of three
- Stop using std::endl
- Why is “using namespace std” considered bad practice?
add a comment |
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), () { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
- Rule of three
- Stop using std::endl
- Why is “using namespace std” considered bad practice?
add a comment |
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), () { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
- Rule of three
- Stop using std::endl
- Why is “using namespace std” considered bad practice?
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), () { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
- Rule of three
- Stop using std::endl
- Why is “using namespace std” considered bad practice?
answered Nov 11 at 14:36
SourceChris
563
563
add a comment |
add a comment |
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
add a comment |
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
add a comment |
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
answered Nov 11 at 13:42
Bo R
616110
616110
add a comment |
add a comment |
You may want std::fill.
– Jesper Juhl
Nov 11 at 13:38
2
This question shows how you want to solve a problem. The problem with the question is that you don't tell us the actual problem you want to solve, you only ask us how to fix this solution to your unknown problem. That's a very typical XY problem. Please try to ask us about the real problem you want to solve, tell us your solution to it (which you have) and perhaps we will be able to help you solve the real problem in a perhaps better way. If not then we will help you with the solution you have.
– Some programmer dude
Nov 11 at 13:39
2
Also, in C++ never use
malloc
andfree
, not even for primitive types likeint
arrays. Always begin withstd::vector
. And you need to learn about the rules of three/five/zero, and with astd::vector
you can follow the rule of zero which I recommend.– Some programmer dude
Nov 11 at 13:42
1
malloc
/free
should never be used in C++ programs. They don't call constructors/destructors. Usenew
/delete
instead - well, not really; please use containers and/or smart pointers instead of manual memory management.– Jesper Juhl
Nov 11 at 13:45
2
This is only my guess -- There is no need to guess. The
std::vector
implementation for your compiler is readily available to you by opening up the#include <vector>
header. Or simply debug and step through to see how that constructor works. In any event, it is likely that thestd::vector
class usesplacement-new
, not a naive "create a temporary and copy" as you would believe. The programmers writing the implementation ofstd::vector
are some of the best professionals in the world -- they are well aware of optimizing these things far more than the average C++ programmer.– PaulMcKenzie
Nov 11 at 14:02