[C++系列] 41. 详解OJ---请设计一个类,该类只能在栈上创建对象

1)不论是只能在堆上创建对象、只能在栈上创建对象,构造函数必须得封死。如果不封死构造函数,在任何地方均可创建对象,包括在类外也能够创建对象。

class Stack {
private:
	Stack(){}                // 封死构造函数
};

int main() {
	
	system("pause");
	return 0;
}

2)现在也无法再任何地点创建对象。需要提供静态方法,供创建栈上对象,在方法内创建对象,Stack s; return &s;但是该函数在函数体内创建出局部变量,返回一个局部变量出来。但是实质上是值拷贝,当函数需要返回一个对象,他会在栈中创建一个临时对象,存储函数的返回值。即拷贝出一个临时的匿名对象出来,放在外部的函数栈帧当中。匿名对象创建出就立马进行返回了,在编译器返回时遇到匿名对象时会做优化,直接调用一次构造函数,在外部创建一个对象。

class Stack {
public:
	static Stack GetStack() {            // 静态方法
		Stack s;                     // 在栈上生成对象
		return s;                    // 返回发生值拷贝
	}

	Stack(const Stack& s) {               // 拷贝构造
		cout << "Stack(const Stack& s)" << endl;
	}
private:
	Stack() {
		cout << "Stack()" << endl;
	}
};

int main() {
	Stack s = Stack::GetStack();

	system("pause");
	return 0;
}

即先函数内部调用构造函数,返回时再调用拷贝构造函数。

class Stack {
public:
	static Stack GetStack() {
		// Stack s;
		return Stack();            // 写成匿名对象形式,Stack()相当于调用构造函数,
                                           // 创建一个匿名对象再返回,编译器的内部优化
	}

	Stack(const Stack& s) {
		cout << "Stack(const Stack& s)" << endl;
	}
private:
	Stack() {
		cout << "Stack()" << endl;
	}
};

int main() {
	Stack s = Stack::GetStack();

	system("pause");
	return 0;
}

 

 return返回时编译器调用构造函数,并且马上进行返回,即编译器进行内部优化,创建匿名对象直接进行返回,少调用一次拷贝构造,提高效率。

3)在此思考,拷贝构造需要封死吗?大可不必这么敏感,保持清醒头脑,切勿草木皆兵啊。答案是不必的,因为拷贝构造出来的对象仍然在栈上啊,并且函数在返回时也调用了拷贝构造的!

4)C++11新写法,直接将operator new只声明不实现

class Stack {
	void* operator new(size_t n) = delete;
private:
	// void* operator new(size_t n);
};

int main() {
	Stack s = Stack::GetStack();

	system("pause");
	return 0;
}

对于这种写法来讲,再调用new是无法调用的,因为new底层也是依靠operator new实现的。malloc可以操作,但是malloc是创建对象吗?malloc只是申请空间,算作是一个小bug吧。但是却可以在类外部直接创建对象

class Stack {
	// void* operator new(size_t n) = delete;
public:
	void* operator delete(void* p) = delete;
private:
	void* operator new(size_t n);
	void* operator delete(void* p);
};
// 构造函数仍然公有

Stack s;							// 在数据段仍然可以创建对象    

int main() {
	Stack* p = new Stack();			// new 只声明不实现,调不动
	delete p;						// delete只声明不实现,也调不动

	//Stack* ps = (Stack*)malloc(sizeof(Stack));	// 先利用malloc申请空间
	//new(ps) Stack;			// 再调new的定位表达式,调构造函数,但是构造函数私有无法调动



	system("pause");
	return 0;
}

综上所述:还是推荐写上面那种方式,下面采用C++11新语法封死operator new的方式,其既可以在栈上创建对象,还可以在数据段创建对象。且注意C++11未封死构造函数,构造函数公有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值