小编Ziz*_*Tai的帖子

为什么shared_ptr使用placement new

我在许多地方读过,当make_shared<T>用于创建一个时shared_ptr<T>,它的控制块包含一个足够大的存储块来容纳一个T,然后该对象是在存储内部构建的,具有新的位置.像这样的东西:

template<typename T>
struct shared_ptr_control_block {
    std::atomic<long> count;
    std::atomic<long> weak_count;
    std::aligned_storage_t<sizeof (T), alignof (T)> storage;
};
Run Code Online (Sandbox Code Playgroud)

但我有点困惑为什么我们不能只有一个成员变量与类型T?为什么要创建原始存储然后使用新的贴图?不能与普通的类型对象一步合并T吗?

c++ c++11

15
推荐指数
2
解决办法
1661
查看次数

GCC和Clang对constexpr构造函数的不同行为

对于这个结构:

struct Wrapper {
    int value;

    constexpr explicit Wrapper(int v) noexcept : value(v) {}
    Wrapper(const Wrapper& that) noexcept : value(that.value) {}
};
Run Code Online (Sandbox Code Playgroud)

而这个功能:

constexpr Wrapper makeWrapper(int v)
{
    return Wrapper(v);
}
Run Code Online (Sandbox Code Playgroud)

以下代码无法为Clang(Apple LLVM版本7.3.0)编译,但是对于GCC(4.9+)编译良好,两者都具有-Wall -Wextra -Werror -pedantic-errors:

constexpr auto x = makeWrapper(123);
Run Code Online (Sandbox Code Playgroud)

Clang抱怨说"非constexpr构造函数'Wrapper'不能用于常量表达式." 哪个编译器是对的?

c++ c++11

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

std :: unique_ptr constexpr构造函数

如图所示这里,std::unique_ptr有两个constexpr构造空指针:

constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );
Run Code Online (Sandbox Code Playgroud)

我对这两个构造函数有两个问题:

  1. 为什么我们需要两个?我们不能只声明一个:

    constexpr unique_ptr( nullptr_t = nullptr );
    
    Run Code Online (Sandbox Code Playgroud)
  2. constexpr真的有用吗?我尝试在我的代码中执行此操作,但它没有编译(g ++ 6.1.0,-std=c++14):

    constexpr std::unique_ptr<int> p;
    // error: the type 'const std::unique_ptr<int>' of constexpr variable 'p'
    // is not literal because 'std::unique_ptr<int>' has a non-trivial destructor
    
    Run Code Online (Sandbox Code Playgroud)

c++ c++11 c++14

14
推荐指数
2
解决办法
1552
查看次数

嵌套的shared_ptr销毁会导致堆栈溢出

这是一个更多的设计问题(我知道为什么会发生这种情况,只是想看看人们如何处理它).假设我有一个简单的链表struct:

struct List {
    int head;
    std::shared_ptr<List> tail;
};
Run Code Online (Sandbox Code Playgroud)

shared_ptr使多个列表之间的子列表的共享.但是,当列表变得很长时,可能会在其析构函数中发生堆栈溢出(由shared_ptrs 的递归释放引起).我尝试过使用显式堆栈,但由于尾部可以由多个列表拥有,因此非常棘手.如何设计我List以避免这个问题?

更新:澄清一下,我不是要重新发明轮子(std::forward_list).在List以上所述,仅为实际数据结构的简化版本.真正的数据结构是一个有向的非循环图,如果你想到它只是很多带有共享尾部/头部的链表.复制图表通常非常昂贵,因此数据共享是必要的.

更新2:我正在考虑显式遍历指针链并随时移动std::move.就像是:

~List()
{
    auto p = std::move(tail);
    while (p->tail != nullptr && p->tail.use_count() == 1) {
        // Some other thread may start pointing to `p->tail`
        // and increases its use count before the next line
        p = std::move(p->tail);
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎在单个线程中工作,但我担心线程安全.

c++

12
推荐指数
2
解决办法
637
查看次数

接受值或rvalue引用的仅移动参数

这个帖子的接受答案通过价值与通过右值参考传递说明:

对于仅移动类型(as std::unique_ptr),pass-by-value似乎是常态......

我对此有点怀疑.让我们说有一些不可复制的类型,Foo移动也不便宜; 和一些Bar有成员的类型Foo.

class Foo {
public:
    Foo(const Foo&) = delete;
    Foo(Foo&&) { /* quite some work */ }
    ...
};

class Bar {
public:
    Bar(Foo f) : f_(std::move(f)) {}    // (1)
    Bar(Foo&& f) : f_(std::move(f)) {}  // (2)
    // Assuming only one of (1) and (2) exists at a time

private:
    Foo f_;
};
Run Code Online (Sandbox Code Playgroud)

然后为以下代码:

Foo f;
...
Bar bar(std::move(f));
Run Code Online (Sandbox Code Playgroud)

构造函数(1)引发2个移动构造,而构造函数(2)只引发1.我还记得在Scott Meyers的Effective Modern C++中读到这个但是不能立即记住哪个项目.

所以我的问题是,对于仅移动类型(或者更一般地说,当我们想要转移参数的所有权时),我们是否应该更倾向于通过rvalue-reference来获得更好的性能?

更新: …

c++ c++11

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

阻止许多锁/期货/等.直到任何准备好

是否有可能阻止一组锁/期货/任何可阻止的实体,直到其中任何一个准备就绪?我们的想法是:

std::vector<std::future<T>> futures = ...;
auto ready_future = wait_until_an_element_is_ready(futures);
process(ready_future.get());
Run Code Online (Sandbox Code Playgroud)

我记得像libevent,libev和libuv这样的库具有IO任务的这种能力.但我不知道这些是否可以用于锁/期货.

我想到的一种方法就是让期货在完成后调用一个处理程序,但同时将处理程序比较并交换为null,这样其他期货就不能调用它.然而,这需要协调期货,因此无法对锁进行.

更新:似乎有一个针对C++ 2x 的提议.

c++ multithreading c++11

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

C++核心指南中的stack_array

C++核心指南提到了一个名为a的东西stack_array.它的用法如下:

const int n = 7;
int m = 9;

void f()
{
    std::array<int, n> a1;
    stack_array<int> a2(m);  // A stack-allocated array.
                             // The number of elements are determined
                             // at construction and fixed thereafter.
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是如何实施这样的课程呢?我们如何在运行时动态确定堆栈大小?

c++ c++11

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

“cargo clippy”是“cargo check”的超集吗?

我正在尝试使用 CI 构建和测试我的 Rust 代码,我想知道cargo clippy(可能带有选项)是否涵盖了所有cargo check功能。我只需要运行cargo clippy,还是需要同时运行?

rust rust-cargo

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

传递给std :: result_of之前的衰减类型

如本页http://en.cppreference.com/w/cpp/thread/async所示std::async,C++ 14中的一个签名已从C++ 11版本更改

template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type>
    async( Function&& f, Args&&... args );
Run Code Online (Sandbox Code Playgroud)

template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
    async( Function&& f, Args&&... args );
Run Code Online (Sandbox Code Playgroud)

更改是在std::decay_t传递给函数和参数类型之前应用于函数和参数类型的s(将参考和cv限定符和衰减数组/函数移除到指针中)std::result_of.我不太明白为什么腐烂是有用的.例如,对于一个功能类型Fn(可能是封闭类的类型别名),传递Fn,Fn&&,const Fn&等等似乎都产生相同的结果.

有人能给我一个具体的例子,其中衰变是有用的吗?

更新:例如,这段代码:

#include <iostream>
#include <type_traits>

int main()
{
    auto fn = [](auto x) -> int { return x + 1; };

    using Fn = decltype(fn);
    using FnRef = Fn&;
    using FnCRef …
Run Code Online (Sandbox Code Playgroud)

c++ templates c++11 c++14

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

在高阶函数中完美转发可调用对象

我一直在写这样的高阶函数:

template<typename F, typename... Args>
void doStuff(F f, Args&&... args)
{
    // ...
    f(std::forward<Args>(args)...);
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者可以替换F fF&& f.

但在我了解了ref-qualifiers(哎哟)之后,情况变得复杂了.想象一个仿函数类:

struct Foo {
    void operator()(...) &;
    void operator()(...) &&;
};
Run Code Online (Sandbox Code Playgroud)

然后我之前的实现doStuff将只调用该&方法,因为参数总是左值.

我认为解决这个问题的方法是这样实现doStuff:

template<typename F, typename... Args>
void doStuff(F&& f, Args&&... args)
{
    // ...
    std::forward<F>(f)(std::forward<Args>(args)...);
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这也是如何std::result_of可能实现的.我想知道的是,这个实现有什么缺点,即我应该用它替换所有的HOF实现吗?

c++ c++11

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

标签 统计

c++ ×9

c++11 ×8

c++14 ×2

multithreading ×1

rust ×1

rust-cargo ×1

templates ×1