我需要与内部类共享一些变量( myMap )。我尝试使用以下方法来做到这一点:
class SecondClass {
public:
std::map< std::string, short > *myMapPtr;
};
class TestClass {
public:
SecondClass secondClass;
std::map< std::string, short > myMap;
TestClass() {
printf( "consturctor of TextClass\n" );
secondClass.myMapPtr = &myMap;
}
~TestClass() {
printf( "desturctor of TextClass\n" );
}
};
int main() {
std::vector< TestClass > objArr;
{
TestClass newObj;
objArr.push_back( newObj );
}
int i = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
}
问题在于我无法再访问 objArr [0] .secondClass.myMapPtr 。您可以编译此代码并看到它返回错误:&#34; EXC_BAD_ACCESS&#34;在线:
int i = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
这里有什么问题? objArr应该在其中存储创建的对象。为什么它不能这样工作?
UPD 2: @rcrmn,谢谢。但我不明白为什么当我在std :: vector中添加另一个元素时,它会破坏我之前的指针:
std::vector< TestClass > objArr;
{
TestClass newObj;
objArr.push_back( newObj );
objArr[ 0 ].secondClass.myMapPtr = &objArr[ 0 ].myMap;
}
int i1 = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
{
TestClass newObj;
objArr.push_back( newObj );
objArr[ 1 ].secondClass.myMapPtr = &objArr[ 1 ].myMap;
}
int i2 = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
问题出在最后一行。但为什么?我没有改变objArr的第一个元素,为什么我无法访问第一个元素? (&#34; int i2&#34; line)。
UPD 3 即使我做了这样的事情:
std::vector< TestClass > objArr;
{
TestClass newObj;
objArr.push_back( newObj );
}
objArr[ 0 ].secondClass.myMapPtr = &objArr[ 0 ].myMap;
{
TestClass newObj;
objArr.push_back( newObj );
}
objArr[ 1 ].secondClass.myMapPtr = &objArr[ 1 ].myMap;
int i = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
我也有这个错误,但是为什么......在范围结束后我存储指向&amp; objArr [0] .myMap 的指针,它不应该改变元素的地址了。哪里有我的错?
答案 0 :(得分:3)
在主类中,您将创建一个范围内名称newObj引用的对象。在它的构造函数中,它采用指向其std::map
的指针并将其存储在内部类中。
TestClass() {
printf( "consturctor of TextClass\n" );
secondClass.myMapPtr = &myMap; // <- the problem
}
问题是push_back
按原样复制对象,内部对象对std::map
的引用仍然引用旧对象的地图。因此,当离开范围时,newObj将被销毁,您的内部引用现在无效。
{
TestClass newObj;
objArr.push_back( newObj );
}
我认为最佳选择是覆盖TestClass
的复制构造函数,以便内部类引用正确的std::map
。
修改强>
问题是你是从java的角度来看它。在C ++中,您没有垃圾收集器,您有范围。未在共享内存中创建的对象(例如,使用new),如方法中的对象变量,在程序流进入范围时创建,并在离开时销毁。
因此,如果您在对象内保留对映射的引用,则当您离开由{}
分隔的作用域时对象将被销毁,该引用将不再是有效的内存位置。
编辑2:
嗯,实际上,现在我认为,std::vector
很可能在增加数组大小时重新分配对象。在这种情况下,对地图的引用将不再有效。
您可以验证预先分配数组的此行为:
std::vector< TestClass > objArr;
objArr.reserve(2);
{
TestClass newObj;
objArr.push_back( newObj );
}
objArr[ 0 ].secondClass.myMapPtr = &objArr[ 0 ].myMap;
{
TestClass newObj;
objArr.push_back( newObj );
}
objArr[ 1 ].secondClass.myMapPtr = &objArr[ 1 ].myMap;
int i = objArr[ 0 ].secondClass.myMapPtr->count( "test" );
但你真的应该使用共享内存。
答案 1 :(得分:1)
因为矢量存储副本并且您没有遵守三条规则。