包含指向 A 类的指针的 B 类中的 A 类初始化
Class A initialisation within class B containing pointer to class A
我希望类A包含一些数据,而类B将包含指向该数据的指针。我通过返回对数据对象 A 的引用的函数提供对数据的访问。如果我创建一个对象 B,那么我可以访问对象 A,但是如果创建一个指向 B 的指针,那么等效的操作会产生分段错误。 喜欢这个:
#include <iostream>
#include <vector>
class A {
public:
A(const int pInt) {mInt = pInt;}
void print() {std::cout << mInt << std::endl;}
private:
int mInt; //some data
};
class B {
public:
B() {mP1 = new A(1);} //initialise to 1
~B() {delete mP1;}
A& access() {return *mP1;} //return reference to the data
private:
A* mP1; //pointer to some data
};
int main() {
B vB;
vB.access().print(); //this works.
B *vBptr;
vBptr->access().print(); //Segmentation fault!
std::vector<B*> vVec;
vVec.resize(1);
vVec[0]->access().print(); //Segmentation fault!
}
我想在创建 B *vBptr 时,B 对象没有初始化?那么,如何创建指向自动初始化的 B 对象的指针向量呢?
干杯。
你需要初始化指针:
B *vBptr = new B;
vBptr->access().print();
这同样适用于您的向量 - 您必须遍历元素并初始化它们。
for ( int i = 0 ; i < vVec.size() ; i++ )
vVec[i] = new B;
请注意,您必须手动释放内存:
delete vBptr;
和
for ( int i = 0 ; i < vVec.size() ; i++ )
delete vVec[i];
不要遇到内存泄漏。
程序中的两个问题
B *vBptr;
您的指针尚未初始化,尽管它是 B 类型的指针,但未指向 B 类型的有效对象。将其更改为
B *vBptr = new B();
vVec.resize(1);
此处调整大小不会为向量的每个元素分配存储。您可以通过向矢量的 resize 方法提供初始化来使用实际对象初始化元素
vVec.resize(1,new B());
你实际上需要将指针设置为某些东西:
B *vBptr; // bad -- uninitialized
B *vBptr = new B; // proper
正如在其他答案中提到的,指针变量不会自动为其分配内存,因此您需要像这样手动分配和释放内存:
B vB;
vB.access().print(); //this works.
B *vBptr = new B;//allocate memory for vBptr
vBptr->access().print();
delete vBptr;//clean up of vBptr
std::vector<B*> vVec;
vVec.push_back(new B);
vVec[0]->access().print();
delete vVec[0];
但是,我建议不要使用原始指针管理内存,因为它很容易获得内存泄漏和错误。 例如,如果抛出异常,上面的代码会泄漏内存vBptr->access().print()
。您的B
类违反了三规则(手动管理资源时的默认复制构造函数/赋值操作(。因此,如果您复制B
对象,就会发生可怕的事情(双释放和访问已删除的内存(。
因此,我建议您使用某种智能指针。如果使用c ++ 11可以使用std::shared_ptr
或std::unique_ptr
,否则有std::tr1::shared_ptr
。如果你的编译器没有 tr1,boost 也有 boost:shared_ptr
。然后,您的代码将如下所示:
class B {
public:
B():mP1(new A(1)) {} //initialise to 1
~B() {} //no extra managing necessary
A& access() {return *mP1;} //return reference to the data
private:
std::shared_ptr<A> mP1; //pointer to some data
};
int main() {
B vB;
vB.access().print(); //this works.
std::shared_ptr<B> vBptr(new B);
vBptr->access().print();
std::vector<std::shared_ptr<B> > vVec;
vVec.push_back(std::shared_ptr<B>(new B));
vVec[0]->access().print();
}
如果您需要最小的开销并且正在使用c ++ 11,std::unique_ptr
是您的朋友,否则iirc boost会boost::unique_ptr
。只是远离std::auto_ptr
.实际上没有理由手动管理内存,除非您喜欢增加错误的复杂性/潜在性,或者您的代码对性能非常敏感(并且使用非常高效的自定义分配器(。
B *vBptr;
vBptr->access().print(); //Segmentation fault!
嗯,当然;你创建了一个变量来存储指向 B 对象的指针,但你实际上并没有让它指向 B 对象。(提示:看到你为 B 类编写的代码,你让 B 的A* mP1
指向某事?
std::vector<B*> vVec;
vVec.resize(1);
vVec[0]->access().print(); //Segmentation fault!
嗯,当然;你创建了一个指向 B 对象的指针向量,然后你调整了向量的大小以添加一个元素;该元素是默认构造的指向 B 的指针。对于指针类型,默认构造是 null 指针,因此您同样不会指向任何实际的 B 对象。
您的问题与任何 A 或 B 实现无关。
那么我怎样才能创建一个指向 B 对象的指针向量
你为什么认为你想这样做?只制作 B 对象的向量有什么问题?
B vB;
vB.access().print();
B *vBptr = &vB; // or B *vBptr = new B;
vBptr->access().print();
std::vector<B*> vVec;
vVec.push_back(&vB); // vVec.push_back(new B);
vVec[0]->access().print();
但是,有必要不这样写B吗?
class B {
public:
// B() {}
// ~B() {}
A& access() {return a;}
private:
A a;};
感谢所有做出贡献的人。以下是我现在采用的实现,即使用 boost::shared_ptr:
#include <iostream>
#include <vector>
#include "boost/smart_ptr.hpp"
class A {
public:
A(const int pInt) {mInt = pInt;}
void print() const {std::cout << mInt << std::endl;}
void set(const int pInt) {mInt = pInt;}
private:
int mInt; //some data
};
class B {
public:
B() {} //leave A pointer as null
~B() { } //delete handled by shared_ptr
A& access() {return *mP1;} //return reference to the data
boost::shared_ptr<A>& access_A_ptr() {return mP1;} //return the pointer for assignment
private:
boost::shared_ptr<A> mP1;
};
int main() {
std::vector< boost::shared_ptr<A> > vVecA; //data to be shared
for (unsigned int i = 0; i < 5; i++) {
boost::shared_ptr<A> vAptr(new A(i));
vVecA.push_back(vAptr);
vVecA[i]->print();
}
vVecA[2]->set(123);
for (unsigned int i = 0; i < vVecA.size(); i++) {
vVecA[i]->print(); //changes to the underlying objects are reflected
}
boost::shared_ptr<B> vBptr(new B); //make an empty B
vBptr->access_A_ptr() = vVecA[2]; //assignment of shared pointer
vBptr->access().print();
std::cout << "use count of vVecA[1] = " << vVecA[1].use_count() << std::endl; // = 1
std::cout << "use count of vVecA[2] = " << vVecA[2].use_count() << std::endl; // = 2
std::vector< boost::shared_ptr<B> > vVecB;
//vVecB.resize(vVecA.size(), boost::shared_ptr<B> (new B) ); //resize and init to a SINGLE B object, NO!!!
for (unsigned int i = 0; i < vVecA.size(); i++) {
vVecB.push_back(boost::shared_ptr<B> (new B)); //filling array with separate empty Bs
vVecB[i]->access_A_ptr() = vVecA[i];
vVecB[i]->access().print(); // = 0,1,123,3,4
}
vVecA[2]->set(2); //changes to A objects reflected in the B objects
for (unsigned int i = 0; i < vVecB.size(); i++) {
vVecB[i]->access().print(); // = 0,1,2,3,4
}
std::cout << "use count of vVecA[1] = " << vVecA[1].use_count() << std::endl; // = 2
std::cout << "use count of vVecA[2] = " << vVecA[2].use_count() << std::endl; // = 3
}
这实际上已成为共享指针的练习。但是,仍然非常欢迎在任何方面发表评论。
谢谢!
- 分段错误 - 读取初始化指针的数组
- 初始化指针的常量向量
- 初始化指针或引用成员变量以指向另一个成员
- C++初始化指针/引用/复制细微差别
- 使用无效指针初始化指针声明符的行为是否未定义?
- 在一行中初始化指针(新uint8_t[高度*宽度*3])
- 如何使用可变模板初始化指针?
- 初始化指针时出现写入访问冲突
- C 错误,带有卷曲括号的字面初始化指针
- 重新初始化指针是一种不好的做法吗?
- 初始化指针?C
- 初始化指针向量的向量
- 如何在类函数中正确初始化指针
- C++初始化指针会使应用程序随机崩溃
- 初始化指针结构 - 内存中的外观
- 如何使用struct构造函数在结构中初始化指针阵列
- 在一行中声明并初始化指针到类实例
- 分配数组与初始化指针
- QT 中的非初始化指针
- 使用地址值初始化指针