在类中实现良好的封装将确保没有外部力量可以修改对象的内部。在C ++中,这意味着一个类应该分配所有需要动态分配的对象本身。如果要对这样的对象进行复制,则意味着必须复制许多内部属性(不仅仅是指针)。这可能会导致某些程序的大量开销。下面给出一个例子:
class A { };
class B : public A {
private:
std::vector< const A* > m_children;
public:
B( ) : m_children( 0 ) { }
B( const B& src ) : m_children( src.m_children.size( ) ) { // Make it a copy of src
for ( unsigned int i = 0; i < m_children.size( ); i++ )
// Make a full copy of src element (and all children, not implemented here)
m_children[ i ] = copyOf( *src.m_children[ i ] ); // Dynamically allocates copy!
}
~B( ){ // Deallocate all children
while ( !m_children.empty( ) ){
delete m_children.back( ); // Get last element in array
m_children.pop_back( ); // Remove last element
}
}
void addChild( const B& child ) {
m_children.push_back( new B( child ) ); // Notice dynamic allocation
}
};
B build( int x ) {
B b;
if ( x != 0 ) b.addChild( build( x - 1 ) );
return b;
}
int main( int argc, char **argv ) {
B b = build( 10 ); // Make 10 generations with 1 child each
}
每次将一个孩子添加到B时,它都会再次完全分配(包括所有孩子)。这确实提供了良好的封装,因为无论在什么情况下,父进程都是唯一可以实际修改其子进程(或解除分配指针)的进程。此外,它完全有责任自行销毁这些儿童。这在内存管理方面不是很有效。必须为每个build()函数动态创建和删除许多其他对象。
如何有两种可能性:
要么我在这里遗漏了一些东西,这可以通过实现良好的封装和效率来实现。如果是这种情况,请告诉我
或者,这是唯一的方法,然后:通常首选哪种方式;强大的封装(没有外部访问),或者在类外部分配对象,因此内存操作发生的次数较少,但是外部世界&#34;有权访问这些指针及其对象(安全性较低)?
答案 0 :(得分:0)
您应该使用移动语义来避免不必要的复制。您需要向class B
添加移动构造函数。
class B
{
B(B&& rhs)
{
std::swap(m_children, rhs.m_children);
}
}
然后,您可以将addChild()
功能更改为:
class B
{
void addChild(B child)
{
m_children.push_back( new B( std::move(child) ) );
}
}
为什么会这样?在build()
函数中,您将临时函数传递给addChild()
。这将调用移动构造函数,然后您只需向前移动对象。
LIVE DEMO - 删除了复制构造函数,因此您可以看到不涉及复制。