比如一个类:
class Test {
public:
std::string s; //s 在浅拷贝的时候,是否会调用 std::string 的拷贝构造?
float a;
}
std::shared_ptr<Test> function() {
...
auto test = Test(); //栈上创建
test.s = "aaa";
test.a = 111;
auto result = std::make_shared<Test>(test); //调用 Test 缺省构造函数,即 memcpy?
return result;
}
int main() {
auto ret = function();
...
}
此时发生浅拷贝,如果直接 memcpy 覆盖过去,那么成员变量 s 指向的字符串的内容是栈上的,离开栈就会发生内存访问错误。但实际测试并没有发生内存错误。
1
norz 2021-02-05 09:24:29 +08:00 1
string 的拷贝构造会执行
|
2
auto8888 2021-02-05 09:27:10 +08:00
string 不是指针成员呢,亲亲。
|
3
norz 2021-02-05 09:28:42 +08:00
浅拷贝并不是 memcpy,而是直接赋值
|
4
owwlo 2021-02-05 09:28:56 +08:00 1
像楼上说的,默认是拷贝构造函数并不会是 memcpy,即使是编译器优化,我“猜”编译器也只会对 std:: is_trivially_copyable 的结构执行 memcpy 。
|
6
freemon 2021-02-05 09:32:05 +08:00
stl::string 抽象出来的代码不是这样吗
|
7
freemon 2021-02-05 09:32:14 +08:00
class string {
enum { _BUF_SIZE = 16 }; union _Bxty { // storage for small buffer or pointer to larger one char _Buf[_BUF_SIZE]; char* _Ptr; } _Bx; size_t _Mysize; // current length of string size_t _Myres; // current storage reserved for string }; |
8
levelworm 2021-02-05 09:54:44 +08:00 via Android
浅拷贝就是一个个 bit 复制过去吧?类里带指针需要在堆上创建对象的必须用深拷贝。
|
9
auto8888 2021-02-05 09:59:57 +08:00
"aaa" 存储在文字常量区
|
10
hitmanx 2021-02-05 10:28:11 +08:00 1
string 不是 const char*,它是把字符串存在 heap 里的。且哪怕是 const char*,这个指针指向也是没问题的。就像楼上说的,"aaa"是在常量区的,而不是注释里写的在栈上
|
11
amaranthf 2021-02-05 10:33:49 +08:00
浅拷贝,指的是一种“变量间赋值的方式”,而“class 的默认复制构造并非浅拷贝”。
class 的默认复制构造函数中,只有对指针成员才会进行浅拷贝,即直接赋值,对对象类型的成员会执行其默认复制构造。 |
12
alazysun 2021-02-05 10:41:03 +08:00
缺省的拷贝构造就是浅拷贝,但对有拷贝构造函数的成员,则会调用它的拷贝构造。
|
13
lvzx 2021-02-05 11:12:26 +08:00 via Android
你自己写个类,拷贝构造加点打印不就知道了?自动生成的拷贝构造函数,会调用成员变量的拷贝构造函数,所以 string 当然不会有问题
|
14
xuanbg 2021-02-05 11:14:03 +08:00
浅拷贝只是复制指针,深拷贝是复制数据+新的指针。
|
15
walker522 2021-02-05 11:44:58 +08:00
深浅拷贝是相对于能否级联复制指针所指内容的,是类型的拷贝函数设计问题。
而正确设计的对象和基本类型是可以自动级联复制。 make_shared 先在堆上分配内存,再执行对象拷贝。 string 拷贝内部会进行了指针内容拷贝,是深拷贝。 |