标签: shared-ptr

std::shared_ptr<T>.use_counter() 的问题

https://en.cppreference.com/w/cpp/memory/shared_ptr/use_count状态:

在多线程环境中,use_count 返回的值是近似值(典型实现使用 memory_order_relaxed 加载)

但这是否意味着use_count()在多线程环境中完全没有用呢?

考虑以下示例,其中该类Circular实现了一个循环缓冲区std::shared_ptr<int>

向用户提供了一种方法 - ,它检查中元素get()的引用计数是否大于 1(我们不希望这样做,因为这意味着它由先前调用 的用户持有)。nextstd::array<std::shared_ptr<int>>get()

如果是<= 1,则将 的副本std::shared_ptr<int>返回给用户。

在这种情况下,用户是两个线程,除了喜欢调用get()循环缓冲区之外什么都不做——这就是他们的人生目的。

在实践中,当我执行该程序时,它会运行几个周期(通过将 a 添加counter到循环缓冲区类进行测试),然后抛出异常,抱怨下一个元素的引用计数器为> 1

use_count()这是多线程环境下返回的值是近似值这一说法的结果吗?

是否有可能调整底层机制,使其具有确定性并按照我希望的方式运行?

如果我的想法是正确的 -在 的函数内部,元素use_count()的(或者更确切地说,用户的实际数量)next永远不应该增加到 1 以上,因为只有两个消费者,并且每次线程调用 时,它已经释放了旧的(已复制)(这又意味着剩余的驻留应该只有 1 的引用计数)。get()Circularget()std::shared_ptr<int>std::shared_ptr<int>Circular::ints_

#include <mutex>
#include <array>
#include <memory>
#include <exception>
#include <thread>

class Circular {
    public:
      Circular() {
          for …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading reference-counting shared-ptr

1
推荐指数
1
解决办法
178
查看次数

std::make_shared 导致未定义的行为,但新的作品

考虑以下示例类:

class Foo {

public:
    void* const arr_;

    Foo() = delete;

    Foo(const size_t size, bool high_precision) :
        arr_(Initialize(size, high_precision)) {};

    template <typename T>
    T* GetDataPointer() {
        return (T* const)arr_;
    }
private:
    static void* Initialize(const size_t size, bool high_prec) {
        if (high_prec) {
            return new double[size];
        }
        else {
            return new float[size];
        }
    }

};
Run Code Online (Sandbox Code Playgroud)

当我使用 创建指向 Foo 对象的共享指针时std::make_shared,我经常发现我初始化的数组数据显示未定义的行为/变得损坏。例如:

std::shared_ptr<Foo> sp_foo = std::make_shared<Foo>(Foo(3,false));
    auto foo_data = sp_foo->GetDataPointer<float>();
    foo_data[0] = 1.1;
    foo_data[1] = 2.2;
    foo_data[2] = 3.3;
    std::cout << "First …
Run Code Online (Sandbox Code Playgroud)

c++ memory shared-ptr

1
推荐指数
1
解决办法
526
查看次数

在lambda中捕获shared_ptr

我想在 lambda 表达式中捕获共享指针。尝试了两种方法:

\n
    \n
  1. 捕获共享指针

    \n

    错误:非静态数据成员 A::ptr 的使用无效

    \n
  2. \n
  3. 创建一个弱指针并捕获它(通过网上的一些结果找到这个)。我不确定我的做法是否正确

    \n

    错误: \xe2\x80\x98const 类 std::weak_ptr\xe2\x80\x99 没有名为 \xe2\x80\x98someFunction\xe2\x80\x99 的成员

    \n
  4. \n
\n

在有人将其标记为重复之前,我知道它可能与其他一些问题类似,但他们的解决方案似乎都不适合我。想知道我做错了什么以及如何解决它,这就是我来这里的原因。

\n

文件.h

\n
#include "file2.h"\n\nclass A{\n   private:\n      uint doSomething();\n      std::shared_ptr<file2> ptr;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

文件.cpp

\n
#include "file.h"\n\nuint A::doSomething(){\n   ...\n\n   // Tried using weak pointer\n   //std::weak_ptr<Z> Ptr = std::make_shared<Z>();\n   \n   auto t1 = [ptr](){\n   auto value = ptr->someFunction;}\n   \n   // auto t1 = [Ptr](){\n   // auto value = Ptr.someFunction;}\n   \n   ...\n   }\n
Run Code Online (Sandbox Code Playgroud)\n

c++ lambda shared-ptr weak-ptr

1
推荐指数
1
解决办法
6515
查看次数

为什么 std::shared_ptr 中的计数器是原子的?

_Sp_counted_base使用原子计数器的实现:

_Atomic_word  _M_use_count;     // #shared
_Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
Run Code Online (Sandbox Code Playgroud)

为什么计数器是原子的而指针不是?原子计数有必要吗?有没有例子说明其必要性?

(因为std::shared_ptr不是线程安全的,所以我认为原子计数是没有必要的。)

c++ shared-ptr

1
推荐指数
1
解决办法
403
查看次数

为什么标准允许空但非空的shared_ptr?

    \n
  1. 这个问题与 std::shared_ptr 不同,std::shared_ptr 为空但不为 null。\n该问题是关于解决特定问题,而我是在询问某个标准功能背后的基本原理和设计原因。
  2. \n
  3. 这个问题是另一个问题的前身:为什么需要空weak_ptr来存储空指针,而空shared_ptr允许存储非空指针?在某种程度上,它们具有相同的背景。然而,我相信这个问题是独立的并且本身是可以回答的。
  4. \n
\n

C++ 标准提供了一个别名构造函数shared_ptr

\n
template <typename T>\nclass shared_ptr\n{\n    template <typename U>\n    shared_ptr(const shared_ptr<U>& r, element_type* ptr);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

这样的构造函数意味着一个shared_ptr对象可以以一种方式创建,它拥有一个对象,与 所拥有的相同r,同时存储指向另一个对象的指针 - ptr

\n

此外,标准明确允许使用此构造函数创建一个shared_ptr不拥有任何东西的对象(从而满足“空”的定义),但仍然指向某个对象(因此被限定为“非空”) :

\n
\n

[util.smartptr.shared.const]:
\n17。[注2:此构造函数允许使用非空存储指针创建空的shared_\xc2\xadptr 实例。\xe2\x80\x94 尾注]

\n
\n

构造一个空但非空的shared_ptr实例很容易被禁止,例如要求尝试构造shared_ptr具有非空存储指针的空实例应该抛出异常。

\n

但标准选择允许它。我想知道为什么以及为什么。

\n

空但非 null 的预期和规范使用场景是什么shared_ptr

\n

c++ language-design shared-ptr c++17

1
推荐指数
1
解决办法
113
查看次数

使用私有析构函数创建仅shared_ptr的类?

我有一个在线程之间传递的数据类。我希望这个类成为std::shared_ptr唯一一个不能通过从外部调用其析构函数来销毁的类,因此我也希望析构函数是私有的。我目前的解决方案是

template<typename T>
struct DestructorHelper
{
    static void Destroy(void* v) { delete static_cast<T*>(v); }
};

class SharedOnly
{
public:
    SharedOnly(const SharedOnly& other) = delete; // deleted copy constructor
    SharedOnly& operator=(const SharedOnly& other) = delete; // deleted copy assignment operator
    SharedOnly(SharedOnly&& other) = delete; // deleted move constructor
    SharedOnly& operator=(SharedOnly&& other) = delete; // deleted move assignment operator

    static std::shared_ptr<SharedOnly> create()
    {
        auto objPtr = new SharedOnly;
        auto desPtr = &DestructorHelper<SharedOnly>::Destroy;
        std::shared_ptr<SharedOnly> shared(objPtr, desPtr);
        return shared;
    }

private:
    SharedOnly() …
Run Code Online (Sandbox Code Playgroud)

c++ shared-ptr c++20

1
推荐指数
1
解决办法
182
查看次数

为什么不调用复制构造函数?

#include <iostream>
#include <memory>

using namespace std;

class Init {
private:
    int x;
public:
    Init(int y) {
        x = y;
        cout << "default constructor called" << endl;
        
    }
    
    Init(std::shared_ptr<Init> z) {
        this->x = z->x;
        cout << "copy constructor called" << endl;
    }
};

int main()
{
    int k = 5;
    std::shared_ptr<Init> a = std::make_shared<Init>(k);
    std::shared_ptr<Init> b(a);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的期望是同时调用默认构造函数和复制构造函数,但只调用默认构造函数。可能是什么问题?

输出是: 默认构造函数称为

c++ smart-pointers copy-constructor shared-ptr default-constructor

1
推荐指数
1
解决办法
126
查看次数

为什么 std::make_shared&lt;T&gt; 不是 std::shared_ptr&lt;T&gt; 的静态函数,即 std::shared_ptr&lt;T&gt;::make?

这是一个关于理解设计决策的问题,而不是对错误或缺陷的抱怨。

在C++标准库中,创建共享指针及其对象的函数是直函数,

template< class T, class... Args> std::shared_ptr<T> make_shared( Args&&... args );
Run Code Online (Sandbox Code Playgroud)

为什么这个函数不是static的函数shared_ptr<T>,如下所示:

template <class... Args> std::shared_ptr<T>::make(Args&&... args);
Run Code Online (Sandbox Code Playgroud)

这将使std::命名空间更加整洁,并且还允许这样的事情:

using shared_vector = std::shared_ptr<std::vector<int>>;

shared_vector a = shared_vector::make(7);
Run Code Online (Sandbox Code Playgroud)

c++ language-design shared-ptr

1
推荐指数
1
解决办法
69
查看次数

如何在表达式中触发 std::shared_ptr 的 bool 运算符(即 `bool is_empty = shared_ptr1 &amp;&amp; shared_ptr2;` )?

鉴于cur_front_rescur_back_res都是shared_ptr, std::shared_ptr 的 bool 运算符如何在表达式(即bool is_empty = cur_front_res && cur_back_res;)中触发?

仅仅因为如果操作数(即 before和 after )不是 bool 类型,&&总是会导致内置转换?&&&&

下面的代码片段确实有效

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> cur_front_res; // Empty shared_ptr
    std::shared_ptr<int> cur_back_res(new int(42)); // Shared_ptr pointing to an int

    bool is_empty = cur_front_res && cur_back_res;

    if (is_empty) {
        std::cout << "Both cur_front_res and cur_back_res are not empty" << std::endl;
    } else {
        std::cout << "Either cur_front_res or cur_back_res is empty" …
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers shared-ptr c++14

1
推荐指数
1
解决办法
66
查看次数

交换2个shared_ptr的内容

交换两个s的内容时shared_ptr,只交换内容。当在shared_ptr交换之前从另一个副本创建一个副本时,我很惊讶新shared_ptr副本的内容保持不变。

这是一个例子:

std::shared_ptr<int> foo (new int(10));
std::shared_ptr<int> bar (new int(20));

auto abc = foo;
std::swap (foo, bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
std::cout << "abc: " << *abc << '\n';
Run Code Online (Sandbox Code Playgroud)

它打印:

foo: 20
bar: 10
abc: 10
Run Code Online (Sandbox Code Playgroud)

abc在这种情况下为什么不是20?鉴于它是 的副本foo

c++ shared-ptr

1
推荐指数
1
解决办法
92
查看次数