I'm not sure why this is happening when I add a mutex member to myClass(in this example mu):
Error C2661 "'std::tuple<
void (__thiscall MyNameSpace::myClass::* )(void),MyNameSpace::myClass>::tuple': no overloaded function takes 2 arguments include\memory 2438
namespace MyNameSpace{
class myClass{
shared_ptr<myClass2> property;
mutex mu;
public:
myClass(shared_ptr<myClass2> arg):property(std::move(arg)) {
}
void Run(){
...........
}
}
class myClass2{
public:
myClass2(std::string str) {
trace(str);
}
}
}
int main(){
shared_ptr<myClass2> new_obj(new myClass2("somthing"));
thread(&myClass::Run, myClass(new_obj)).join();
.......other stuff.....
}
and How can i overcome this?
It is a compilation error, not a memory error.
Note that std::mutex is not copiable. So, the class containing it becomes non-copiable as well.
I guess (as you do not show the relevant code) that you attempt to copy an instance of myClass, and that causes the above compilation error.
In particular, you can search places in your code, where you pass or return myClass instances by value.
UPDATE: As pointed out by #NathanOliver, such a place in the above snippet is:
thread(&myClass::Run, myClass(new_obj))
where a temporary myClass is created.
Related
I have an Object class and ObjectManager class that is supposed to hold pointers to Objects created on the heap and is in charge of housekeeping. i.e., (I don't want to have pointers to temporary Objects, for instance when an object is passed to a function by value). I'd like to do some process on the items in the ObjectManager class and later release the memory.
Please consider the following files:
"Object.h" file
#pragma once
#include<algorithm>
#include "ObjectManager.h"
class ObjectManager;
class Object{
private:
int value;
static bool heap_flag;
public:
Object() {
if (heap_flag) {
heap_flag = false;
ObjectManager::vo.push_back(this);
}
}
~Object() {}
void* operator new (size_t sz){
heap_flag = true;
return malloc(sz);
}
void setValue(int v) { value = v; }
};
and "ObjectManager.h"
#pragma once
#include "Object.h"
#include <vector>
using namespace std;
class Object;
class ObjectManager{
private:
ObjectManager() {}
public:
static vector <Object*> vo; // vector that holds pointers to all objects created on heap
static void releaseObjects() {
size_t index = 0;
for (auto o : vo){
// iterate through the vector and delete the object create on heap
delete o;
vo[index] = NULL;
index++;
}
}
};
finally in the client code:
#include <iostream>
#include "Object.h"
#include "ObjectManager.h"
using namespace std;
bool Object::heap_flag = false;
vector<Object*> ObjectManager::vo;
void process_Heap_objects (vector<Object*>) {
// ... code to iterate through the elements of a vector and do some process
}
int main() {
Object o; // created on stack
Object* po = new Object(); // created on heap
ObjectManager::vo[0]->setValue(100);
process_Heap_Objects(ObjectManager::vo);
ObjectManager::releaseObjects();
return 0;
}
when I compile this file I get the following warning in VS2013 -> "warning C4150: deletion of pointer to incomplete type 'Object'; no destructor called
1> Objectmanager.h: see declaration of 'Object'"
the code compiles fine and works as expected though.
two questions:
1- what does the warning mean?
2- is this a good design? is there a better way to achieve this? what are your thoughts?
You can't call a destructor on a forward declared class.
You must put the destructor call in a compilation unit where it can see the declaration of the destructor (e.g. where you #include the Object.h).
Also, stylistic tips:
On pass by value:
If the object is not going to be mutated or copied by the method, pass by const ref foo (const Object& bar) {}
If the object is going to be mutated but not copied by the method, pass by reference foo (Object& bar) {}
If the object is going to be copied by the method, pass by value
If the method takes possession of the object, pass by pointer
pragma once is not officially part of the standard, and rarely offers faster compilation in current generation compilers. Most style guides recommended to use include guards:
#ifndef SOME_NAME
#define SOME_NAME
... body ...
#endif
Your problem is you are defining and implementing both Object and ObjectManager in the header files. This creates a circular dependency because each header file includes the other.
A better approach would be to only have the class definitions in the headers and the bodies of the methods in cpp files.
The warning you're receiving is due to Object not being defined. Because you have #pragma once you aren't seeing the error you should be seeing (the effect of the circular dependency.) This is preventing the ObjectManager from seeing how the Object class is defined.
I have written a class Seat in cpp & I declared a function pointer it it.
class implimentation is given below
Seat.cpp
#include "StdAfx.h"
#include "Seat.h"
int Seat::count = FL;
Seat::Seat(void)
{
seatId = Seat::count;
seatStatus = unoccupied;
Seat::count++;
}
Seat::~Seat(void)
{
}
void Seat::*checkSeatStatus(void)
{
}
Seat.h
#include <string>
using namespace std;
class Seat :
public Vehicle
{
int seatId;
int seatStatus;
static int count;
public:
Seat(void);
~Seat(void);
void (*checkSeatStatus)();
};
it showing error at function pointer declaration :
'checkSeatStatus' : illegal use of type 'void'
What is the reason behind ? , does it need any initialization of function pointer ?
If checkSeatStatus is intended to be a member function it should be:
void* Seat::checkSeatStatus(void) {
...
}
with function prototype within the class declaration of:
void* checkSeatStatus(void);
If it's intended to be a member variable holding a function pointer that you can set then, umm, don't do that... It's very probably the wrong design.
If (per the name) it's just supposed to return the current value of status then it should be a function that returns an int instead of a void *:
int Seat::checkStatus(void) {
return status;
}
NB: I removed Seat from the method name since it should be implicit from the fact that you called it on a Seat object.
This doesn't answer the question you ask, but will show how to use the function in a thread.
Using std::thread it's actually very easy to start a thread using any member function. The important part is that it should be a normal member function, so declared like
class Seat
{
...
public:
...
void checkSeatStatus();
};
Then to create a thread using the function you first need an instance of the class:
Seat seat;
And then you simply create the thread
std::thread my_thread{&Seat::checkSeatStatus, seat};
Do whatever other processing you want to do in the main thread, and then join the thread you had created:
my_thread.join();
There are a couple of important things to know here: The instance of the Seat class (the variable seat above) must live longer than the thread. If it goes out of scope and is destructed before the end of the thread that will lead to undefined behavior.
You must also join the tread before the thread-object (the variable my_thread above) is destructed.
In the following code the bad method fails to compile, but the good method does not. Why is providing the explicit reference to this making a difference here?
#include <mutex>
class Foo
{
private:
std::mutex lock_;
public:
Foo() = default;
~Foo() = default;
void bad();
void good();
};
void Foo::bad()
{
std::lock_guard<std::mutex>(lock_);
}
void Foo::good()
{
std::lock_guard<std::mutex>(this->lock_);
}
int main()
{
return 0;
}
compile error:
test.cpp: In member function ‘void Foo::bad()’:
test.cpp:18:36: error: no matching function for call to ‘std::lock_guard<std::mutex>::lock_guard()’
std::lock_guard<std::mutex>(lock_);
You can play with the ideone if you want.
This is an instance of the most vexing parse. The parentheses here don't do what you think they do. This:
std::lock_guard<std::mutex>(lock_);
is equivalent to:
std::lock_guard<std::mutex> lock_;
which should make it clear why what you're trying to do won't compile, and why you're getting the compile error you're getting. What you need to do is provide a name for the lock_guard:
std::lock_guard<std::mutex> _(lock_);
The good version works because the this-> qualification prevents the name from being able to be treated as an identifier.
Note: lock_ is a std::mutex and not any kind of lock, which makes it a very confusing name. You should name it something more reflective of what it is. Like mutex_.
If you declare your lock_guard correctly, they both work:
void Foo::bad()
{
std::lock_guard<std::mutex> x{lock_};
}
void Foo::good()
{
std::lock_guard<std::mutex> y{this->lock_};
}
Using a temporary is almost useless, because the lock gets released immediately. Correct usage is to declare a local variable with automatic lifetime.
You need to actually create a variable, for example
std::lock_guard<std::mutex> lg(lock_);
I need to use a map with various type within es int,int or char,int or char,char....
This is my c++ code:
#include <iostream>
#include<map>
using namespace std;
template< class A, class B >
class MyClass {
private:
std::map<A,B> DatMap;
public:
MyClass<K,T>(){
DatMap = 0;
}
~MyClass(){
delete DatMap;
}
void DatInsert( A k ,B v ) {
DatMap.insert( std::pair<A,B>( k, v) );
}
};
int main(){
DatMap<int,int> datmap1();
diz1.DatInsert();
}
I found this error on: diz1.DatInsert(); line
the error is:
error: request for member ‘DatInsert’ in ‘datmap1’, which is of non-class type ‘DatMap<int, int>()’|
What am I doing wrong?
This is a function declaration:
// functon datamap1, returns DatMap<int, int>
DatMap<int,int> datmap1();
You need
DatMap<int,int> datmap1;
Alternatively, this syntax is valid since C++11
DatMap<int,int> datmap1{};
Vlad and Jauncho make good points but have both missed another error
DatMap<int,int> datmap1(); isn't valid also because there is no public type DatMap exposed. The class is MyClass
You should be saying:
MyClass<int,int> datmap1; // or datmap1{};
There are several errors in the code.
For example identifiers K and T used in this code snippet
MyClass<K,T>(){
DatMap = 0;
}
are undefined. Also the assignment DataMap by zero is invalid.
You shall not delete DatMap in destructor
~MyClass(){
delete DatMap;
}
because DatMap is not a pointer.
These both statements in main
DatMap<int,int> datmap1();
diz1.DatInsert();
are invalid. The first one is a declaration of a function that shall not be compiled. And the second statement contains call of member function DatInsert without arguments. You defined the function as having two parameters
void DatInsert(A k ,B v){
DatMap.insert(std::pair<A,B>(k,v));
}
so you need to provide two arguments.
Actually I want to extract shared_ptr from 'this' object in an another function.
For the same suppose we have a situation where a "Thing member function" needs to pass a pointer to "this" object to another function like:
#include "stdafx.h"
#include<memory>
using namespace std;
class Thing {
public:
void foo();
void defrangulate();
};
void Thing::defrangulate()
{
}
void transformIt(shared_ptr<Thing> ptr)
{
ptr->defrangulate();
/* etc. */
}
void Thing::foo()
{
// we need to transformIt this object
shared_ptr<Thing> sp_for_this(this);
transformIt(sp_for_this);
}
int main()
{
shared_ptr<Thing> t1(new Thing);// start a manager object for the Thing
t1->foo();
}
output:
Debug Assertion failed!
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Am I doing any mistake which causing this run time exception ?
You are causing a double-delete. That's because when you create a shared_ptr from this, you don't tell it that the raw pointer is already owned by someone else. You need to either use a custom, no-op deleter (construct shared_ptr with (this, [](void*){}), or use std::enable_shared_from_this.