考慮這個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 代碼庫并為其添加了一些特性。
uj5u.com熱心網友回復:
std::vector和其他標準容器總是存盤物件的副本。
當您這樣做時auto vec = vector<A>{a};,a將復制到向量中,因此對向量的任何更改都不會影響a.
uj5u.com熱心網友回復:
In main(),a.b不指向有效的vector,因此訪問a.b->size()是未定義的行為。
bar()創建一個 newvector來保存傳遞給它的物件的副本。然后作用于那個復制的物件,而不是.Afoo() AAmain()
如果要foo()作用于 中的原始A物件main(),則必須更改bar()以將 a 傳遞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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/440070.html
