[英]Share class memory over shared_ptr
I want to share object memory between different objects (eg Reader/Writer access same memory pool). 我想在不同对象之间共享对象内存(例如,读取器/写入器访问相同的内存池)。 It works quit good but I have a problem with sharing one shared_ptr.
它工作正常,但是共享一个shared_ptr存在问题。
struct A {
A() {}
A(const A &other) {
i = other.i;
}
std::shared_ptr<int> i;
};
struct B : public A {
B(const A &other) : A(other) {}
};
I would like to get the second example to work, but it throws an exception. 我想让第二个示例工作,但是会引发异常。 Because the variable i is not initialized and the shared_ptr does not get copied (he is empty).
因为变量i未初始化,并且shared_ptr未被复制(他为空)。
{ // don´t throw
A a;
a.i = std::make_shared<int>(10);
B b(a);
*b.i = 11;
printf("%d\n", *a.i);
}
{ // throw
A a;
B b(a);
b.i = std::make_shared<int>(10);
printf("%d\n", *a.i);
}
Only B should init variable i. 只有B应该初始化变量i。
One solution would be following, but do I really need an other wrapper class? 接下来是一个解决方案,但是我真的需要另一个包装器类吗?
struct A {
A() : i(std::make_shared<std::vector<std::shared_ptr<int>>>()) {}
A(const A &other) {
i = other.i;
}
std::shared_ptr<std::vector<std::shared_ptr<int>>> i;
};
struct B : public A {
B(const A &other) : A(other) {}
};
int main(int argc, char *argv[]) {
{ // throw
A a;
B b(a);
b.i->emplace_back(std::make_shared<int>(10));
printf("%d\n", *a.i->at(0));
}
}
Another example would be just to use raw pointer but I want to ask you, how it could work with a shared_ptr. 另一个例子是仅使用原始指针,但我想问你,它如何与shared_ptr一起工作。
The type int is just an example. int类型只是一个例子。 It could also be an heavy class without default constructor.
如果没有默认构造函数,它也可能是一个繁重的类。
Your code throws, because: 您的代码引发,因为:
a
, ai
is an empty shared_ptr
a
, ai
是一个空shared_ptr
b
with a constructor copying a
. a
的构造函数创建b
。 So bi
is then an empty shared_ptr
bi
是一个空的shared_ptr
bi
. bi
的新创建对象。 But this doesn't change the ai
pointer, which is still empty. ai
指针,后者仍然为空。 ai
. ai
。 But as ai is empty, ie has a usage count of 0 and no valid pointer, it's undefined behaviour (probably a segfault will happen). You could easily avoid this pitfall by defining the default constructor of A: 通过定义A的默认构造函数,您可以轻松避免这种陷阱:
A() : i(std::make_shared<int>(0)) {}
a
and b
would then point to the same shared object, and you wouldn't experience the segfault. 然后,
a
和b
将指向相同的共享对象,并且您将不会遇到段错误。
But this approach doesn't of course prevent that someone reassigns bi
to another shared pointer. 但是,这种方法当然不能防止有人将
bi
重新分配给另一个共享指针。 That's the problem with the struct
: you give the key to the house and it's up to you to clean the mess. 这就是
struct
的问题:您将钥匙交给房子,然后由您来清理混乱。
An improved variant could be a completely encapsulated class, where i would be protected and functions or operator give access to i. 改进的变体可以是完全封装的类,其中我将受到保护,而函数或运算符可以访问i。 I choose a way where I overload assignment form int and converion to int, to allow an intuitive usage, but this is a matter of taste:
我选择了一种方法,可以将赋值形式int和converion重载为int,以实现直观的用法,但这只是一个问题:
class A {
public:
A() : i(std::make_shared<int>(0)) {}
A(const A &other) { i = other.i; }
operator int() { return *i; } // you can use A when you could use an int
A& operator= (int x) {
*i = x;
return *this;
}
// todo: copy assigment: take the pointer or take the value ?
protected:
std::shared_ptr<int> i;
};
struct B : public A {
B(const A &other) : A(other) {}
B& operator= (int x) {
*i = x;
return *this;
}
// todo: copy assigment: take the pointer or take the value ?
};
The usage of this class would then be: 此类的用法为:
{ // don´t throw
A a;
a = 10;
B b(a);
b = 11;
printf("%d\n", (int)a);
}
{ // don't throw either
A a;
B b(a);
a = 1;
cout << a <<endl;
cout << b << endl;
b = 10;
printf("%d\n", (int)a); // to make sure that only the int value is passed
}
In this scenario, you've changed to use a shared pointer to a vector of shared pointer. 在这种情况下,您已更改为使用共享指针指向共享指针的向量。
I can see no problem with this code and I've experienced no throwing: see online demo 我看不到这段代码有问题,也没有抛出异常: 请参阅在线演示
You can of course work with raw pointers, provided they've been properly allocated with new. 如果原始指针已正确分配了新指针,那么您当然可以使用它们。
int *pi = new int(1);
shared_ptr<int> spi(pi);
But attention: once you do this, the shared_ptr has ownership. 但请注意:执行此操作后,shared_ptr便拥有所有权。 THis means that the shared_ptr becomes responsible for the destruction of the object.
这意味着shared_ptr负责破坏对象。
If you would reuse this raw pointer in another shared_ptr (or worse: if it was obtained from a shared_ptr), your compiler would'nt complain, but you'd get undefined behaviour at runtime, because when the the second shared_ptr would try to destroy an object that was already destroyed by the first shared_ptr (shared_ptr won't be aware of existance of other shared_ptr if constructed from a raw pointer). 如果要在另一个shared_ptr中重用此原始指针(或更糟糕的是,如果它是从shared_ptr获得的),则编译器不会抱怨,但是在运行时会出现未定义的行为,因为当第二个shared_ptr试图破坏时一个已经被第一个shared_ptr销毁的对象(如果从原始指针构造,则sharedd_ptr将不知道其他shared_ptr的存在)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.