I have a vector ex:TestStructVec of objects for ex:TestStruct, where object contains a vector of unique pointers ex: uptrVec.
struct TestClass {};
struct TestStruct
{
std::vector<std::unique_ptr<TestClass> > uptrVec;
}
std::vector<TestStruct> TestStructVec;
TestStruct ts1;
ts1.uptrVec.emplace_back(std::make_unique<TestClass>());
Now, when emplace back this object to vector, only in vs2013 , c++11, it fails with attempt to reference the deleted function (assuming its some copy const issue). I
TestStructVec.emplace_back(std::move(ts1));
Pls let me know where im doing it wrong.
NOTE: In VS2015, and Vs2017 it compiles Fine and no error is observed.
Any recommendation is appreciated. Thanks.
std::make_unique is only available from c++14 onwards
you can see it here : https://en.cppreference.com/w/cpp/memory/unique_ptr
in section Non-member functions > make_unique > version (in green) :
Related
CPP check is complaining about this construction:
void setThing(std::shared_ptr<Thing> theThing)
{
memberThing = theThing;
}
where memberThing is a std::shared_ptr<Thing>.
When changing to:
void setThing(const std::shared_ptr<Thing>& theThing);
cppcheck is not complaining anymore.
I need a shared pointer, I can't guarantee theThing will exist forever, so I don't want to have a member reference. But why is a const reference working when assigning it to a not-reference member? And what happens actually? Is the shared pointer copied to memberThing? Where did the reference go?
And actually exactly the same question for
void setThings(std::vector<std::shared_ptr<Thing>> theThings)
{
memberThings = theThings;
}
where memberThing is a std::vector<std::shared_ptr<Thing>>.
When using this construction, what is happening with the vector? Is it copied? What happens when the original vector is destroyed? Can I better use the first version or the second?
I am quite confused a const vector& can be assigned to a vector (not-reference). Is that a good idea anyway? What is the best thing to do in this situation? And why?
I have the following struct in a vector
struct ub_node {
const size_t index;
const double ub_dist;
bool operator<(const ub_node &rhs) const { return ub_dist< rhs.ub_dist; }
};
I would like to sort that vector. I have tried using std::sort but I get a compile error:
error: use of deleted function ‘ub_node& ub_node::operator=(ub_node&&)’ with a reference to the line where I do std::sort(result.begin(), result.end());, where result is of type vector<ub_node>.
As far as I understand, the const does NOT affect the execution time, but merely ensures that the programmer (me) does not do anything stupid. If this is the case, I might remove the const and try to ensure that I do not change the node afterwards. Can someone confirm this? Or help me to sort it?
As far as I understand, the const does NOT affect the execution time, but merely ensures that the programmer (me) does not do anything stupid.
Correct.
Sorting a vector swaps the elements around, which is not possible if the elements have immutable data (with your ub_node type you can't even remove or insert an element anywhere except the end of the vector, because that also needs to modify existing elements).
I suggest you remove the const from your members, so the type is possible to modify, and then structure your code so that parts of the program which shouldn't modify it only interacts with the class through const ub_node& or const ub_node*.
That means that the class is modifiable when necessary, but won't be modified by parts of the program that aren't supposed to modify it.
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;
}
}
I'm playing with some code found on net, some of You may know it :)
Using C++11 with this template I can not do this (for T=std::string):
struct some_struct_t
{
T container;
std::atomic<some_struct_t*> next;
};
typedef typename std::aligned_storage<sizeof(some_struct_t), std::alignment_of<some_struct_t>::value>::type some_struct_aligned_t;
This compiles well, but if You try to touch node->container
some_struct_t* node = reinterpret_cast<some_struct_t*>(new some_struct_aligned_t);
You'll get Segmentation fault, because std:string is not initialized properly.
I don't want boost or classes, just plain C++11 and struct.
How can I extened my struct to work with std:string? Is it possible?
void* raw_storage = new some_struct_aligned_t;
some_struct_t* p = new(raw_storage) some_struct_t;
Though it's not clear what the point of the exercise is. Plain old new some_struct_t is guaranteed to allocate a properly aligned storage.
I'm building a compiler with reflection.emit in my spare time, and i've come to a problem that i'm not understanding.
A little context, I've a runtime with a couple of types and one of them is Float2, a simpler vector struct with two float values (X and Y). I've made a couple of properties that allow me to swizzle the values (a la hlsl). For example if i have a new Float2(1.0f, 2.0f), if i make something like (new Float2(1.0f, 2.0f)).YX i'm going to get a Float2(2.0f, 1.0f)
I'm using this type in my language and currently testing this case (minor details of the language omitted):
float2 a = float2(1.0, 2.0).yx;
return a;
I'm transforming float2(1.0, 2.0) in a new call and accessing the property YX of my Float2 type in .yx.
The problem is I'm getting a "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". I don't understand why because if I make something like this:
float2 a = float2(1.0, 2.0);
return a;
Everything goes well.
The IL code that i'm generating is the following (I think the problem occurs in "L_0014: stloc.0", I don't know why it happens though) :
.method public virtual final instance valuetype
[Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 Main() cil managed
{
.maxstack 3
.locals init (
[0] valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 num)
L_0000: ldc.r4 1
L_0005: ldc.r4 2
L_000a: newobj instance void [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::.ctor(float32, float32)
L_000f: call instance valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::get_XY()
L_0014: stloc.0
L_0015: ldloc.0
L_0016: ret
}
Result of peverify:
[IL]: Error: [offset 0x0000000F]
[found value 'Bifrost.Psl.Compiler.Runtime.Float2'][expected address of value 'Bifrost.Psl.Compiler.Runtime.Float2'] Unexpected type on the stack.
The IL looks OK, although I don't know what your Float2 looks like.
I found the best way to debug this is to save the assembly to disk, then run peverify. Any code that generates an AccessViolationException will cause an error in peverify.
Edit: The newobj doc on MSDN talks about pushing an object reference onto the stack, which I took to be a pointer to a value type. If you're getting this error from peverify then I think you need to
newobj
stloc to a temporary variable
ldloca to get the address of the value type stored in the temporary variable
call
Now that I think about it, this is what the C# compiler does if you do a direct call on a value type like 4.ToString();.