我有一个类被设计为一些boost共享内存的包装器。当我尝试将named_mutex作为类成员并在构造函数中初始化它时,我得到编译错误。以下是相关代码:
template< class T > class SharedMemoryVal
{
public:
SharedMemoryVal( const std::string &name, bool readOnly );
SharedMemoryVal( const SharedMemoryVal& other )
{
name = other.name;
mutexName = other.mutexName;
permissions = other.permissions;
shm = other.shm;
mutex = boost::interprocess::named_upgradable_mutex( boost::interprocess::open_or_create, mutexName.c_str() );
}
const SharedMemoryVal& operator=( const SharedMemoryVal& other )
{
if( this == &other )
return *this;
name = other.name;
mutexName = other.mutexName;
permissions = other.permissions;
shm = other.shm;
mutex = boost::interprocess::named_upgradable_mutex( boost::interprocess::open_or_create, mutexName.c_str() );
}
int8_t GetVal( T *val );
int8_t SetVal( T val );
virtual ~SharedMemoryVal();
private:
std::string name;
std::string mutexName;
boost::interprocess::mode_t permissions;
boost::interprocess::shared_memory_object shm;
mutable boost::interprocess::named_upgradable_mutex mutex;
};
using namespace boost::interprocess;
/**
* Construct new shared memory data value
* @param[in] name - Name of shared memory segment
* @param[in] readOnly
*/
template< class T > SharedMemoryVal< T >::SharedMemoryVal( const std::string &name, bool readOnly )
{
// Set name
this->name = name;
// Create mutex
mutexName = this->name.append( "_mutex" );
/* GETTING AN ERROR HERE */
/* error: \u2018boost::interprocess::named_upgradable_mutex::named_upgradable_mutex()\u2019 is private*/
mutex = named_upgradable_mutex( open_or_create, mutexName.c_str() );
//Create a shared memory object.
if( readOnly )
{
permissions = read_only;
shm = shared_memory_object( open_only, name.c_str(), read_only );
}
else
{
permissions = read_write;
shm = shared_memory_object( create_only, name.c_str(), read_write );
// Set size
shm.truncate( sizeof(T) );
}
}
template< class T > SharedMemoryVal< T >::~SharedMemoryVal()
{
shared_memory_object::remove( name.c_str() );
named_upgradable_mutex::remove( mutexName.c_str() );
}
/**
* Return current data value
* @return current data value
*/
template< class T > int8_t SharedMemoryVal< T >::GetVal( T *val )
{
int8_t retVal = -1;
//Map the whole shared memory in this process
mapped_region region( shm, permissions );
// Get data pointer
T *data = static_cast< T * >( region.get_address() );
// Lock
{
// This will only lock if someone else is writing.
// Multiple processes can read at the same time
sharable_lock< named_upgradable_mutex > lock( mutex );
// If there wasn't a problem getting the data
if( data != NULL )
{
*val = *data;
retVal = 0;
}
}
return retVal;
}
/**
* Set shared memory data value
* @param[in] val - value to set
*/
template< class T > int8_t SharedMemoryVal< T >::SetVal( T val )
{
int8_t retVal = -1;
//Map the whole shared memory in this process
mapped_region region( shm, permissions );
// Get data pointer
T *data = static_cast< T * >( region.get_address() );
// Do lock
{
// Lock will always be unlocked at the end of this block
scoped_lock< named_upgradable_mutex > lock( mutex );
// If we got the data OK
if( data != NULL )
{
*data = val;
retVal = 0;
}
}
return retVal;
}
我在创建锁定对象的构造函数中遇到错误,但我无法弄清楚原因。我读到我必须定义自己的复制构造函数和赋值运算符,并且我已经完成了。有什么想法吗?
答案 0 :(得分:1)
您收到错误是因为必须初始化互斥锁成员。
这是通过默认构造函数发生的。在这种情况下,这是私人的。因此,您会收到错误(关于boost :: interprocess :: named_upgradable_mutex的默认构造函数named_upgradable_mutex()是私有的)。
您拥有的代码实际上会发生什么:在进入SharedMemoryVal构造函数的主体之前,将使用其默认构造函数初始化互斥锁成员。然后在正文中,您将新构造的对象分配给互斥锁成员。如果named_upgradable_mutex的默认(无参数)构造函数是公共的(因为默认构造没有名称的互斥体是无意义的),即使它效率低也可行。但
我建议您阅读Scott Meyers的Effective C ++(以及更有效的C ++)。如果你没有它们,我建议你买它们。在Effective C ++第1章第4项中确保对象在使用之前已初始化&#39;如果你在ctor体中为你的成员变量分配(如上所述的默认构造+赋值)而不是在初始化列表中初始化它们(仅构造),你会得到类似的解释。
在更有效的C ++中,您有两个项目。 第12项:首选初始化为构造函数中的赋值。
和
第13项:按照声明的顺序列出初始化列表中的成员。 (这与下面关于初始化顺序的说明有关)更详细。
一些说明上述行为的在线资料:Why preffer member initialization over assignment?
要解决此问题,请将互斥锁的构造移至初始化列表。有关成员初始值设定项列表的更多信息,请Member initializer list
像:
template< class T > SharedMemoryVal< T >::
SharedMemoryVal( const std::string &name, bool readOnly ) :
mutexName( name.append("_mutex") ),
mutex (open_or_create, mutexName.c_str() )
{
}
注意:请注意初始化顺序,并确保在互斥之前初始化mutexName。 如果你在SharedMemoryVal类声明中的mutex之后声明mutexName成员,那么在使用它时调用mutex构造函数时,mutexName将是未初始化的,因为初始化按头中的声明顺序发生,而不是按成员初始化列表的顺序发生。在你的情况下,你在互斥之前声明了mutexName,所以你会没事的。只是在标题中的互斥量之后不要移动它的声明......我想也应该提一下。