C++中函数返回对象并赋值给变量的实现方法咨询
嘿,作为C++初学者能想到拷贝构造和赋值运算符,这个思路已经很到位啦!不过其实你的代码大部分场景下不需要手动实现这些函数,下面我来一步步拆解:
一、先纠正一个小误区
你提到的拷贝构造函数写法myObj::myObj(myObj mO)是有问题的——拷贝构造的参数必须是const引用(const myObj&),如果传值的话,调用拷贝构造时需要先把实参拷贝成形参,这又会触发拷贝构造,陷入无限递归。正确的拷贝构造声明应该是:
myObj(const myObj& other);
另外,myObj = myObj(f());这种写法完全没必要,原代码里的myObj mO = f();是合法的拷贝初始化(C++11及以后还可能触发移动初始化),甚至编译器会通过**返回值优化(RVO)**直接在mO的内存位置构造f()返回的对象,连拷贝/移动操作都能省略。
二、你的代码什么时候能直接运行?
如果myObj是没有动态分配资源的简单类/结构体(比如只包含int、double、std::string这类自带拷贝语义的成员),C++编译器会自动为它生成以下默认函数:
- 默认构造函数
- 拷贝构造函数
- 拷贝赋值运算符
- 移动构造函数(C++11+)
- 移动赋值运算符(C++11+)
这时候你的原代码不需要任何额外操作就能正常运行!
可运行示例:简单版myObj
#include <iostream> #include <string> // 简单的myObj结构体,编译器自动生成所有必要的拷贝/移动函数 struct myObj { int id; std::string name; // 自定义构造函数(可选,方便初始化) myObj(int i, const std::string& n) : id(i), name(n) {} }; myObj f() { // 构造并返回一个myObj实例 return myObj(123, "TestObject"); } int main() { myObj mO = f(); // 完全合法,不需要手动写任何拷贝/赋值函数 std::cout << "ID: " << mO.id << ", Name: " << mO.name << std::endl; return 0; }
运行这段代码会输出:ID: 123, Name: TestObject
三、什么时候需要手动实现拷贝构造/赋值运算符?
只有当myObj包含手动管理的动态资源(比如用new分配的内存)时,默认的浅拷贝会导致问题(比如两个对象指向同一块内存,析构时双重释放),这时候才需要手动实现深拷贝的拷贝构造和赋值运算符,或者改用智能指针(比如std::unique_ptr/std::shared_ptr)来自动管理资源,避免手动编写这些函数。
示例:带动态资源的myObj(用智能指针简化)
#include <iostream> #include <memory> struct myObj { // 用std::unique_ptr管理动态内存,编译器自动生成的拷贝函数会被禁用(因为unique_ptr不可拷贝) // 如果需要拷贝,可以改用std::shared_ptr std::unique_ptr<int> data; myObj(int val) : data(std::make_unique<int>(val)) {} // 如果需要支持拷贝,手动实现拷贝构造(用shared_ptr的话不需要) myObj(const myObj& other) : data(std::make_unique<int>(*other.data)) {} // 拷贝赋值运算符 myObj& operator=(const myObj& other) { if (this != &other) { *data = *other.data; // 或者重新分配:data = std::make_unique<int>(*other.data); } return *this; } }; myObj f() { return myObj(456); } int main() { myObj mO = f(); std::cout << "Data value: " << *mO.data << std::endl; return 0; }
总结
你的想法有一定道理,但不是必须的:
- 普通类/结构体:编译器自动生成所需的拷贝/移动函数,原代码直接可用
- 带动态资源的类:要么手动实现深拷贝的拷贝构造和赋值运算符,要么用智能指针简化资源管理
- 你提到的拷贝构造写法需要修正为引用参数,否则会触发无限递归
内容的提问来源于stack exchange,提问作者User12547645

