为什么这个共享指针的赋值在从嵌套函数返回后没有效果?
Why did this assignment of a shared pointer have no effect after returning from nested function?
考虑这个 mwe:
#include<iostream>
#include<memory>
#include<vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back().b = c;
cout << "Foo size " << vec.back().b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A>{a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}
这是程序的输出:
~ ./a.out
Foo size 1
[1] 107400 segmentation fault (core dumped) ./a.out
为什么 a.b->size()
产生段错误,而不是让包含 42 的向量报告其大小?
背景:我对C++只有很肤浅的了解。通常我在 Python 中编程,但最近(几周前)我开始研究别人的 C++ 代码库并向其添加一些功能。
std::vector
和其他标准容器始终存储对象的副本。
当您执行 auto vec = vector<A>{a};
时,a
被复制到矢量中,因此对矢量的任何更改都不会影响 a
。
在 main()
中,a.b
没有指向有效的 vector
,因此访问 a.b->size()
是 未定义的行为 .
bar()
创建一个新的 vector
,其中包含传入的 A
对象的 副本 。 foo()
然后作用于 复制的 A
对象,而不是 main()
.
中的原始 A
对象
如果您希望 foo()
作用于 main()
中的原始 A
对象,则必须更改 bar()
以传递 vector<A*>
到 foo()
,例如:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A*> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back()->b = c;
cout << "Foo size " << vec.back()->b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A*>{&a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}
考虑这个 mwe:
#include<iostream>
#include<memory>
#include<vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back().b = c;
cout << "Foo size " << vec.back().b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A>{a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}
这是程序的输出:
~ ./a.out
Foo size 1
[1] 107400 segmentation fault (core dumped) ./a.out
为什么 a.b->size()
产生段错误,而不是让包含 42 的向量报告其大小?
背景:我对C++只有很肤浅的了解。通常我在 Python 中编程,但最近(几周前)我开始研究别人的 C++ 代码库并向其添加一些功能。
std::vector
和其他标准容器始终存储对象的副本。
当您执行 auto vec = vector<A>{a};
时,a
被复制到矢量中,因此对矢量的任何更改都不会影响 a
。
在 main()
中,a.b
没有指向有效的 vector
,因此访问 a.b->size()
是 未定义的行为 .
bar()
创建一个新的 vector
,其中包含传入的 A
对象的 副本 。 foo()
然后作用于 复制的 A
对象,而不是 main()
.
A
对象
如果您希望 foo()
作用于 main()
中的原始 A
对象,则必须更改 bar()
以传递 vector<A*>
到 foo()
,例如:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A*> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back()->b = c;
cout << "Foo size " << vec.back()->b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A*>{&a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}