在 C++ 中如何将 push_back 一个 shared_ptr 变量转换为 shared_ptr 的向量?
How do you push_back a shared_ptr variable to a vector of shared_ptrs in C++?
我是 C++ 初学者,有 Python、Java 和 JS 背景,所以在指针方面我仍在学习中。
我有一个共享指针向量。在另一个函数内部,我将一个共享指针分配给一个变量并将其添加到向量中。如果我在该函数退出后尝试访问添加的元素,则会发生分段错误:
class Bar
{
private:
std::vector<std::shared_ptr<Foo>> fooVector;
}
void Bar::addToFoo()
{
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
}
void Bar::otherMethod()
{
// this method gets called sometime after addToFoo gets called
…
fooVector[anIndex]->baz(); // segfaults
…
}
但是,如果 push_back 共享指针而不是变量,它就可以工作。
// this works:
fooVector.push_back(std::shared_ptr<Foo>(new Foo(…)));
// this segfaults:
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
我相信这是因为 foo
变量在 addToFoo
函数退出时被删除(如果我错了请纠正我)。在 C++ 中,如何将 push_back
shared_ptr
变量 转换为 shared_ptrs
的 vector
?
为什么要使用变量
虽然将 shared_ptr
s 直接推送到向量而不使用变量是可行的,但我更喜欢使用变量来执行此操作:
std::shared_ptr<Rider> rider;
switch (iProcessorModesParam)
{
case PEAKS_MODE:
rider = std::shared_ptr<Rider>(new PeaksRider(…));
break;
case RMS_MODE:
rider = std::shared_ptr<Rider>(new RMSrider(…));
break;
}
volumeRiders.push_back(rider);
PeaksRider 和 RMSrider 是 Rider 的子类。我想将 Rider 的所有子类型存储在相同的 Riders 向量中。我了解到将 Rider 的子类型添加到 Riders 的向量中是行不通的,需要指针才能实现这种多态性:
std::vector<Rider> // doesn’t work with subtypes
std::vector<*Rider>
std::vector<std::shared_ptr<Rider>>
拥有 std::shared_ptr<Rider> rider;
变量可以避免为每种类型的 Rider 重复 .push_back(…)
代码。
不是分配共享指针,而是用户 reset
方法。
rider.reset(new PeaksRider(…));
除此之外,您的代码片段对我来说似乎没问题。
段错误可能是由于索引变量(可能超出范围)引起的。我建议你使用 .at(index)
从 vector 访问指针并将那部分代码包装在 try..catch
块中,看看什么是真正的错误。
关于...
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong).
这不是真的,share_ptrs 对 #of 引用使用本地计数器。一旦您将指针推向向量,计数器就会增加到 2,并且在控制退出函数后发生事件,计数器就会减少到 1。因此,您的对象还没有被销毁。
创建共享指针实例,将其存储在变量中,然后对向量执行 push_back 没有问题。只要您在调用“otherMethod”时使用的索引有效,您的代码就应该没问题。不过,我对您的代码有一些建议:
- 创建shared_ptr时,强烈建议通过“std::make_shared”来创建,以确保您的代码在所有情况下的安全性和正确性。在另一个 post 中,您会找到一个很好的解释:Difference in make_shared and normal shared_ptr in C++
- 当使用可能包含会导致 out-of-bounds 访问(通常会导致分段错误)的值的变量访问向量的位置时,最好在使用向量之前放置断言,因此你会发现这些不受欢迎的情况。
我刚刚写了一个小片段,您可以测试一下以说明我刚才提到的内容:
#include <iostream>
#include <vector>
#include <memory>
#include <cassert>
class Foo
{
public:
int data = 0;
};
class Bar
{
public:
void addNewFoo(int d)
{
std::shared_ptr<Foo> foo(new Foo());
foo->data = d;
fooVector.push_back(foo);
}
void addNewFooImproved(int d)
{
auto foo = std::make_shared<Foo>();
foo->data = d;
fooVector.push_back(foo);
}
void printFoo(int idx)
{
assert(idx < fooVector.size());
std::cout << fooVector[idx]->data << std::endl;
}
private:
std::vector<std::shared_ptr<Foo>> fooVector;
};
int main()
{
Bar b;
b.addNewFoo(10);
b.addNewFoo(12);
b.addNewFooImproved(22);
b.printFoo(1);
b.printFoo(2);
b.printFoo(0);
}
我是 C++ 初学者,有 Python、Java 和 JS 背景,所以在指针方面我仍在学习中。
我有一个共享指针向量。在另一个函数内部,我将一个共享指针分配给一个变量并将其添加到向量中。如果我在该函数退出后尝试访问添加的元素,则会发生分段错误:
class Bar
{
private:
std::vector<std::shared_ptr<Foo>> fooVector;
}
void Bar::addToFoo()
{
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
}
void Bar::otherMethod()
{
// this method gets called sometime after addToFoo gets called
…
fooVector[anIndex]->baz(); // segfaults
…
}
但是,如果 push_back 共享指针而不是变量,它就可以工作。
// this works:
fooVector.push_back(std::shared_ptr<Foo>(new Foo(…)));
// this segfaults:
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
我相信这是因为 foo
变量在 addToFoo
函数退出时被删除(如果我错了请纠正我)。在 C++ 中,如何将 push_back
shared_ptr
变量 转换为 shared_ptrs
的 vector
?
为什么要使用变量
虽然将 shared_ptr
s 直接推送到向量而不使用变量是可行的,但我更喜欢使用变量来执行此操作:
std::shared_ptr<Rider> rider;
switch (iProcessorModesParam)
{
case PEAKS_MODE:
rider = std::shared_ptr<Rider>(new PeaksRider(…));
break;
case RMS_MODE:
rider = std::shared_ptr<Rider>(new RMSrider(…));
break;
}
volumeRiders.push_back(rider);
PeaksRider 和 RMSrider 是 Rider 的子类。我想将 Rider 的所有子类型存储在相同的 Riders 向量中。我了解到将 Rider 的子类型添加到 Riders 的向量中是行不通的,需要指针才能实现这种多态性:
std::vector<Rider> // doesn’t work with subtypes
std::vector<*Rider>
std::vector<std::shared_ptr<Rider>>
拥有 std::shared_ptr<Rider> rider;
变量可以避免为每种类型的 Rider 重复 .push_back(…)
代码。
不是分配共享指针,而是用户 reset
方法。
rider.reset(new PeaksRider(…));
除此之外,您的代码片段对我来说似乎没问题。
段错误可能是由于索引变量(可能超出范围)引起的。我建议你使用 .at(index)
从 vector 访问指针并将那部分代码包装在 try..catch
块中,看看什么是真正的错误。
关于...
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong).
这不是真的,share_ptrs 对 #of 引用使用本地计数器。一旦您将指针推向向量,计数器就会增加到 2,并且在控制退出函数后发生事件,计数器就会减少到 1。因此,您的对象还没有被销毁。
创建共享指针实例,将其存储在变量中,然后对向量执行 push_back 没有问题。只要您在调用“otherMethod”时使用的索引有效,您的代码就应该没问题。不过,我对您的代码有一些建议:
- 创建shared_ptr时,强烈建议通过“std::make_shared”来创建,以确保您的代码在所有情况下的安全性和正确性。在另一个 post 中,您会找到一个很好的解释:Difference in make_shared and normal shared_ptr in C++
- 当使用可能包含会导致 out-of-bounds 访问(通常会导致分段错误)的值的变量访问向量的位置时,最好在使用向量之前放置断言,因此你会发现这些不受欢迎的情况。
我刚刚写了一个小片段,您可以测试一下以说明我刚才提到的内容:
#include <iostream>
#include <vector>
#include <memory>
#include <cassert>
class Foo
{
public:
int data = 0;
};
class Bar
{
public:
void addNewFoo(int d)
{
std::shared_ptr<Foo> foo(new Foo());
foo->data = d;
fooVector.push_back(foo);
}
void addNewFooImproved(int d)
{
auto foo = std::make_shared<Foo>();
foo->data = d;
fooVector.push_back(foo);
}
void printFoo(int idx)
{
assert(idx < fooVector.size());
std::cout << fooVector[idx]->data << std::endl;
}
private:
std::vector<std::shared_ptr<Foo>> fooVector;
};
int main()
{
Bar b;
b.addNewFoo(10);
b.addNewFoo(12);
b.addNewFooImproved(22);
b.printFoo(1);
b.printFoo(2);
b.printFoo(0);
}