Consider the following class:
class Vector{
int dim; //dimension of array v
Complex* v; //Complex is another class
public:
Vector(int dim = 0):dim(dim){(dim)?(v=new Complex[dim]):(v=nullptr);}
Vector(int dim, const Complex* c):dim(dim),v(new Complex[dim]){
for(int i=0;i<dim;i++) v[i]=c[i];}
Vector(const Vector& a):dim(a.dim),v(new Complex[a.dim]){
for(int i=0;i<dim;i++) v[i]=a.v[i];}
~Vector(){if(dim)delete [] v,v=nullptr;}
friend Vector& operator >> (Vector& is,Complex& z){
Vector copie(is);
is.~Vector();
is.Vector::Vector(is.dim+1);}
};
I try to overload the >> operator in order to add elements to v.
My idea was to create a copy, then call dctor and the ctor for the object to
be modified via >> operator.
I'm stuck after getting this error:
In function ‘Vector& operator>>(Vector&, Complex&)’:
main.cc:56:20: error: cannot call constructor ‘Vector::Vector’ directly
is.Vector::Vector(is.dim+1);
I'm not allowed to use containers!!
Please help me!
That's right, you can't call the constructor directly. Probably you want to use placement new.
friend Vector& operator >> (Vector& is,Complex& z){
Vector copie(is);
is.~Vector();
// is.Vector::Vector(is.dim+1);
new(&is) Vector(is.dim + 1);
return is;
}
Even then the code may not be semantically correct.
Having said that, this is not the recommended way to do it for
the last 20 years. Watch this Jon Kalb "Exception-Safe Code, Part
I" for an explanation (the example is almost the same). The
recommended way is to implement this in terms of other operations like
copy or swap.
Minor syntactic detail, operator>> is confusing, use operator<< at worst.
There is no need for calling the destructor and calling the constructor. Steps you can take to make your function work:
Allocate memory to hold the current objects plus the additional object.
Copy the objects from the old memory location to the new memory location.
Delete the old memory.
Associate the newly allocated memory with the input object.
friend Vector& operator>>(Vector& is, Complex& z){
// Allocate memory
Complex* vnew = new Complex[dim+1];
// Copy objects to new memory.
std::copy(is.v, is.v + is.dim, vnew);
vnew[is.dim] = z;
// Delete the old memory.
delete [] is.v;
// Use the new memory
is.v = vnew;
// Increment dim.
is.dim++;
return is;
}
Having said that, I think you are using the wrong function to insert an element to Vector. operator>> is for extracting data from. operator<< is for inserting data to. You should use operator<< to insert an element to a Vector.
friend Vector& operator<<(Vector& is, Complex const& z){
...
}
Related
I'm pretty much trying to make a AddInputEvent but, after a month, can't find a way to turn a local "function from FunctionCallbackInfo"(i'll just call this argf) in to a Persistent Function so that garbage collection doesn't erase the pointers.
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New. This results in a error: cannot convert 'v8::Local<v8::Function>' to 'v8::Function*'
here is the code, not completely sure why I can't convert it
class inputevnt_feld{
public:
char* call_on;
v8::Persistent<v8::Function> func;
};
int entvcount = -1;
vector<inputevnt_feld> event_calls; //this is pretty much a array of events that we can call later
// in js looks like this "AddInputEvent("string", function);"
void AddInputEvent( const v8::FunctionCallbackInfo<v8::Value>& args ) {
v8::HandleScope handle_scope(args.GetIsolate());
//gotta make sure that we ain't letting in some trojan horse that has nothing in it
if (args[1]->IsFunction() && args[0]->IsString()) {
inputevnt_feld newt;
//converts js string to char array
v8::String::Utf8Value str(args.GetIsolate(), args[0]);
const char* cstr = ToCString(str);
newt.call_on = (char*)cstr;
//here is where the problem is with function casting
v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
newt.func = v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
//push the new stuff in to even array
event_calls.push_back(newt);
//getting vector array size is too much for my smol brain
//so I'ma just do this myself
entvcount++;
//cout << event_calls[entvcount].call_on << endl; //debug
}
}
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New
Yes, that's correct. If you know how to read it, the C++ type system is your friend for figuring out the details.
If you look at the definition of v8::PersistentBase<T>::New, you'll see that it takes a T* (for its template type T). If you look at the v8::Local<T> class, you'll see that a way to get a T* from it is to use its operator*. That leads to:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>::New(..., *callback);
Alternatively, you can use the Persistent constructor directly, and pass it the Local without dereferencing it first:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>(..., callback);
Both options are entirely equivalent. Personally I'd prefer the latter as it takes slightly fewer characters to spell out, but that's really the only difference.
(Your current code as posted does something else: it ignores the result of the cast and passes the original args[1] directly to Persistent::New -- that's not going to work.)
I am trying to write my own Allocator which can be used in STL. That far I could almost successfully finish but with one function I have my problem:
The Allocator used in STL should provide the function construct [example from a standard allocator using new & delete]:
// initialize elements of allocated storage p with value value
void construct (T* p, const T& value)
{
::new((void*)p)T(value);
}
I am stuck how to rewrite this using my own function which replaces the new keyword initializing it with the value.
This function construct is for example used in this code: fileLines.push_back( fileLine );
where
MyVector<MyString> fileLines;
MyString fileLine;
These are my typedefs where I use my own Allocator:
template <typename T> using MyVector = std::vector<T, Allocator<T>>;
using MyString = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
I am confused because here is allocated a pointer to T which can be for example [when I understood it correctly] MySstring.
Do I understand it correctly that the pointer - allocated by new - will have 10 bytes, when value is 123456789 and then the provided value is copied to the new pointer?
My question:
How to rewrite the one line of code using my own function? For me the difficult point is how to get the length of value [which can have any type] in order I can correctly determinate the length of the allocated block and how to copy it in order it works for all possible types T?
The new operator in the construct function does not allocate anything at all, it's a placement new call, which takes an already allocated chunk of memory (which needs to have been previously allocated some way, and at least as large as sizeof(T)) and initializes it as a T object by calling the constructor of T, pretending that the memory pointed to by p is a T object.
::new int(7) calls the default new operator, gets some memory big enough for an int, and constructs an int with the value 7 in it.
::new(ptr) int(7) takes a void* called ptr, and constructs an int with the value 7 in it. This is called "placement new".
The important part is what is missing from the second paragraph. It does not create space, but rather constructs an object in some existing space.
It is like saying ptr->T::T() ptr->int::int(7) where we "call the constructorofinton the memory location ofptr, exceptptr->T::T()orptr->int::int(7)are not valid syntaxes. Placementnew` is the way to explicitly call a constructor in C++.
Similarly, ptr->~T() or ptr->~int() will call the destructor on the object located at ptr (however, there is no ~int so that is an error, unless int is a template or dependent type, in which case it is a pseudo-destructor and the call it ignored instead of generating an error).
It is very rare that you want to change construct from the default implementation in an allocator. You might do this if your allocator wants to track creation of objects and attach the information about their arguments, without intrusively modifying the constructor. But this is a corner case.
I have the following member variable in a class:
std::vector<std::unique_ptr<Object>> objects_;
I explicitly want the vector to maintain ownership at all times. I've seen suggestions that in order for a member function to access a pointer in the vector and make changes to the object T wrapped in the std::unique_ptr, we must move the pointer to calling code, i.e:
void foo(int i) {
auto object = std::move( vector.at( i ) ); // move object to caller (caller owns)
object->dosomething();
vector.at(i) = std::move(object); // move back into vector (vector owns)
}
Another method was to work with raw pointers:
void foo(int i) {
Object* object = vector.at( i ).get();
object->doSomething();
}
However, I've been working with this:
void foo(int i) {
auto& object = vector.at( i );
object->doSomething();
}
Which is the correct and most robust method for my case? Does this function ever take ownership of the data in the std::unique_ptr? Is there a way to access Object without playing with the std::unique_ptr?
(excuse me if my methods are incorrect, I hope I got the point across)
The first approach will not retain ownership of the object if object->dosomething() throws an exception (i.e. it is not exception safe) since the second std::move() statement will not be executed.
Assuming C++11, both of the other approaches are effectively equivalent, subject to the assumption that the owned pointer is not null. Under the same assumption, the code can be simplified to
void foo(int i)
{
vector.at(i)->doSomething();
}
which will work with all C++ standards (not just C++11 or later).
It is possible to access the object without monkeying with the unique_ptr - simply store the pointer elsewhere and use that. However, that does compromise the purpose of using std::unique_ptr in the first place. And is error-prone - for example, the std::unique_ptr can destroy the object, and leave those other pointers dangling.
If you are really that worried about the potential of your vector losing ownership, consider using a shared_ptr instead.
I've some code that moves an object into another object. I won't need the original, moved object anymore in the upper level. Thus move is the right choice I think.
However, thinking about safety I wonder if there is a way to invalidate the moved object and thus preventing undefined behaviour if someone accesses it.
Here is a nice example:
// move example
#include <utility> // std::move
#include <vector> // std::vector
#include <string> // std::string
int main () {
std::string foo = "foo-string";
std::string bar = "bar-string";
std::vector<std::string> myvector;
myvector.push_back (foo); // copies
myvector.push_back (std::move(bar)); // moves
return 0;
}
The description says:
The first call to myvector.push_back copies the value of foo into the
vector (foo keeps the value it had before the call). The second call
moves the value of bar into the vector. This transfers its content
into the vector (while bar loses its value, and now is in a valid but
unspecified state).
Is there a way to invalidate bar, such that access to it will cause a compiler error? Something like:
myvector.push_back (std::move(bar)); // moves
invalidate(bar); //something like bar.end() will then result in a compiler error
Edit: And if there is no such thing, why?
Accessing the moved object is not undefined behavior. The moved object is still a valid object, and the program may very well want to continue using said object. For example,
template< typename T >
void swap_by_move(T &a, T &b)
{
using std::move;
T c = move(b);
b = move(a);
a = move(c);
}
The bigger picture answer is because moving or not moving is a decision made at runtime, and giving a compile-time error is a decision made at compile time.
foo(bar); // foo might move or not
bar.baz(); // compile time error or not?
It's not going to work.. you can approximate in compile time analysis, but then it's going to be really difficult for developers to either not get an error or making anything useful in order to keep a valid program or the developer has to make annoying and fragile annotations on functions called to promise not to move the argument.
To put it a different way, you are asking about having a compile time error if you use an integer variable that contains the value 42. Or if you use a pointer that contains a null pointer value. You might be succcessful in implementing an approximate build-time code convention checker using clang the analysis API, however, working on the CFG of the C++ AST and erroring out if you can't prove that std::move has not been called till a given use of a variable.
Move semantics works like that so you get an object in any it's correct state. Correct state means that all fields have correct value, and all internal invariants are still good. That was done because after move you don't actually care about contents of moved object, but stuff like resource management, assignments and destructors should work OK.
All STL classes (and all classed with default move constructor/assignment) just swap it's content with new one, so both states are correct, and it's very easy to implement, fast, and convinient enough.
You can define your class that has isValid field that's generally true and on move (i. e. in move constructor / move assignment) sets that to false. Then your object will have correct state I am invalid. Just don't forget to check it where needed (destructor, assignment etc).
That isValid field can be either one pointer having null value. The point is: you know, that object is in predictable state after move, not just random bytes in memory.
Edit: example of String:
class String {
public:
string data;
private:
bool m_isValid;
public:
String(string const& b): data(b.data), isValid(true) {}
String(String &&b): data(move(b.data)) {
b.m_isValid = false;
}
String const& operator =(String &&b) {
data = move(b.data);
b.m_isValid = false;
return &this;
}
bool isValid() {
return m_isValid;
}
}
Why can not I use new [ ] with smart_pointers?
Actually I can not understand this piece of text.
Caution You should use an auto_prt or shared_ptr object only for
memory allocated by new, not for memory allocated by new []. You
should not use auto_ptr, shared_ptr,orunique_ptr for memory not
allocated via new or, in the case of unique_ptr, via new or new[].
Why can not I use new[] with smart pointers?
In general you can, but that smart pointer must be aware of the fact that it stores a dynamically allocated array, not a single object. This is because objects allocated with operator new[] should be deallocated with operator delete[], not delete. How can a smart pointer know which operator should be applied?
The distinction is made by providing a specialization of smart pointer class templates for array types, like it is currently done in std::unique_ptr<T>:
std::unique_ptr<int> ptr(new int); // will call delete
std::unique_ptr<int[]> arr(new int[5]); // will call delete[]
↑↑
DEMO
However, that syntax does not (yet) apply to all smart pointer types available in the Standard Library.
For comparison, the Boost Smart Pointers library provides separate class templates for storing pointers to dynamically allocated arrays:
boost::shared_array<int> arr1(new int[5]); // will call delete[]
// ~~~~^
boost::scoped_array<int> arr2(new int[5]); // will call delete[]
// ~~~~^
DEMO 2
You should use an auto_ptr or shared_ptr object only for memory allocated by new, not for memory allocated by new [].
std::auto_ptr<T>(† 2017)1 applies a plain delete operator to a pointer it stores, and there is no way to change that behavior. As such, storing a pointer to an array is not an option.
As far as std::shared_ptr<T> is concerned, by default it does the same (calls operator delete). To change that behavior, and properly deallocate a memory area of a stored array, you could use a custom deleter, like std::default_delete<T[]>:
std::shared_ptr<int> arr(new int[5], std::default_delete<int[]>{});
↑↑
or some other provided by yourself:
std::shared_ptr<int> arr(new int[5], [](int* ptr) { delete[] ptr; } );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
DEMO 3
However, a missing specialization for std::shared_ptr<T[]> implies no operator[] that could let you easily access the elements of a stored array, which leads to unintuitive syntax like arr.get()[0].
With proposal N4077 introduced, there will be a specialization for array type pointers:
std::shared_ptr<int[]> arr(new int[5]); // will call delete[]
↑↑
You should not use auto_ptr, shared_ptr, or unique_ptr for memory not allocated via new or, in the case of unique_ptr, via new or new[].
This excerpt simply states that one should not construct a smart pointer from a pointer to an object that was not allocated dynamically, as (by default) it would result in calling delete on something that was not allocated with new (ditto new[]/delete[]).
What is the difference between unique_ptr<double[]> p1(new double[2]);, unique_ptr<double> p2(new double[2]);, unique_ptr<double[]> p3(new double(2)); ?
std::unique_ptr<double[]> p1(new double[2]);
OK: Constructs a unique_ptr from (and takes ownership of) a pointer to an array of two doubles. It will call delete[] to deallocate the memory pointed.
std::unique_ptr<double> p2(new double[2]);
Wrong: Constructs a unique_ptr from (and takes ownership of) a pointer to an array of two doubles. It will call delete (!) to deallocate the memory pointed. (possibly undefined behavior - a mismatch between new[] and delete).
std::unique_ptr<double[]> p3(new double(2));
Wrong: Constructs a unique_ptr from (and takes ownership of) a pointer to a single double initialized to value 2. It will call delete[] (!) to deallocate the memory pointed. (possibly undefined behavior - a mismatch between new and delete[]).
1 std::auto_ptr<T> is deemed deprecated in favor of std::unique_ptr<T> since C++11, and will be removed from the Standard Library in C++1z according to N4168.
Examples:
#include <memory>
int
main()
{
auto p1 = std::unique_ptr<char[]>{new char[3]}; // C++11
auto p2 = std::shared_ptr<char>{new char[3], [](char* p) {delete [] p;}}; // C++11
auto p3 = std::make_unique<char[]>(3); // C++14
}
The first and second are good for C++11 and forward. The 3rd was introduced in C++14. The first and third represent unique ownership of the new, and the second has shared ownership of the new.