小编Nat*_*mal的帖子

C++ volatile关键字是否引入了内存栅栏?

我知道volatile通知编译器可能会更改值,但为了完成此功能,编译器是否需要引入内存栅栏才能使其工作?

根据我的理解,易失性对象的操作顺序不能重新排序,必须保留.这似乎暗示一些内存栅栏是必要的,并且没有真正解决方法.我说的是对的吗?


这个相关问题上有一个有趣的讨论

乔纳森威克利写道:

...对于不同的volatile变量的访问不能由编译器重新排序,只要它们出现在单独的完整表达式中......对于线程安全而言volatile是无用的,但不是由于他给出的原因.这不是因为编译器可能会重新排序对易失性对象的访问,而是因为CPU可能会重新排序它们.原子操作和内存屏障阻止编译器和CPU重新排序

大卫·施瓦茨回答的评论:

...从C++标准的角度来看,编译器执行某些操作与编译器发出导致硬件执行某些操作的指令之间没有区别.如果CPU可能重新排序对volatiles的访问,则标准不要求保留其订单....

... C++标准没有对重新排序有什么区别.你不能争辩说CPU可以重新排序它们没有可观察到的影响,所以没关系--C++标准将它们的顺序定义为可观察的.如果编译器生成的代码使平台能够满足标准要求,则编译器在平台上符合C++标准.如果标准要求对挥发物的访问不能重新排序,则重新排序它们的平台不符合要求....

我的观点是,如果C++标准禁止编译器重新排序对不同易失性的访问,理论上这种访问的顺序是程序可观察行为的一部分,那么它还要求编译器发出禁止CPU执行的代码所以.该标准没有区分编译器的作用以及编译器生成的代码使CPU执行的操作.

这确实产生了两个问题:它们中的任何一个是"正确的"吗?实际的实现到底做了什么?

c++ multithreading volatile c++11

80
推荐指数
8
解决办法
1万
查看次数

特质和政策有什么区别?

我有一个类,我试图配置它的行为.

template<int ModeT, bool IsAsync, bool IsReentrant> ServerTraits;
Run Code Online (Sandbox Code Playgroud)

然后我有我的服务器对象本身:

template<typename TraitsT>
class Server {...};
Run Code Online (Sandbox Code Playgroud)

我的问题是我上面的用法是我的命名错误吗?我的模板化参数实际上是一个策略而不是特征吗?

什么是模板化论证的特征与政策相比?

c++ type-traits policy-based-design template-meta-programming

59
推荐指数
2
解决办法
2万
查看次数

C++编译器如何确保在不同的线程上安全地使用不同但相邻的内存位置?

可以说我有一个结构:

struct Foo {
  char a;  // read and written to by thread 1 only
  char b;  // read and written to by thread 2 only
};
Run Code Online (Sandbox Code Playgroud)

根据我的理解,当两个线程在两个不同的内存位置上运行时,C++标准保证了上述的安全性.

我想尽管如此,因为char a和char b属于同一个缓存行,所以编译器必须进行额外的同步.

这到底发生了什么?

c++ multithreading thread-safety

43
推荐指数
2
解决办法
3131
查看次数

我可以使用placement new来重置shared_ptr中的对象吗?

假设我有一堂课.

class BigData {...};
typedef boost::shared_ptr<BigData> BigDataPtr; 
Run Code Online (Sandbox Code Playgroud)

然后我做:

BigDataPtr bigDataPtr(new BigData());
Run Code Online (Sandbox Code Playgroud)

在我完成了我的对象之后,我确信没有其他用户使用该对象.

执行以下操作是否安全:

bigDataPtr->~BigDataPtr();
new (&*bigDataPtr) BigData;
Run Code Online (Sandbox Code Playgroud)

这会让我重置对象而不需要任何额外的分配吗?

c++ memory performance

8
推荐指数
2
解决办法
1724
查看次数

制作没有成员类成员对象或堆栈对象的仿函数会更有效吗?

我有一个没有成员变量的仿函数.我想知道根据需要动态创建这个仿函数是否更有效,或者将其作为成员变量缓存.关于空基类优化和缓存局部性存在一些我不确定的问题.

struct Foo
{
int operator()(const MyData& data) const { ... }
};
Run Code Online (Sandbox Code Playgroud)

c++ performance

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

如果我设置优化-O3,是否在gcc中完成C++整个程序优化?

我想知道如果我只是在gcc中指定优化级别3(在Ubuntu 12.04上运行的版本4.8.1)或者我是否必须明确指定整个程序优化作为gcc选项,是否完成了整个程序优化?

c++ optimization performance gcc

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

使用以下has_member函数,SFINAE无法正常工作?

我正在尝试Walter Brown的TMP演讲中的例子,我正在尝试让他的has_member实现工作.

然而,实现似乎错误地返回true,这使我相信有一些我不理解的SFINAE的细节.

#include <iostream>
#include <type_traits>

template <class ...>
using void_t = void;

template <class, class = void>
struct has_type_member: std::false_type {};

template <class T> 
struct has_type_member<T, void_t<typename T::type> >: std::true_type {};

struct FooWithType
{
    typedef int type;
};

struct FooNoType 
{
};

int main()
{
    std::cout << "Does FooWithType have type member? " << 
        (has_type_member<FooWithType>() ? "YES" : "NO") << "\n";

    std::cout << "Does FooNoType have type member? " << 
        (has_type_member<FooNoType>() ? "YES" : …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae template-specialization c++11

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

当我使用非cst内存模型时,为什么我的spinlock实现性能最差?

我在下面有两个版本的自旋锁.第一个使用默认值memory_order_cst,而后者使用memory_order_acquire/memory_order_release.由于后者更放松,我希望它有更好的表现.但似乎并非如此.

class SimpleSpinLock
{
public:

    inline SimpleSpinLock(): mFlag(ATOMIC_FLAG_INIT) {}

    inline void lock()
    {   
        int backoff = 0;
        while (mFlag.test_and_set()) { DoWaitBackoff(backoff); }
    }   

    inline void unlock()
    {   
        mFlag.clear();
    }   

private:

    std::atomic_flag mFlag = ATOMIC_FLAG_INIT;
};

class SimpleSpinLock2
{
public:

    inline SimpleSpinLock2(): mFlag(ATOMIC_FLAG_INIT) {}

    inline void lock()
    {   
        int backoff = 0;
        while (mFlag.test_and_set(std::memory_order_acquire)) { DoWaitBackoff(backoff); }
    }   

    inline void unlock()
    {   
        mFlag.clear(std::memory_order_release);
    }   

private:

    std::atomic_flag mFlag = ATOMIC_FLAG_INIT;
};

const int NUM_THREADS = 8;
const int NUM_ITERS = 5000000;

const …
Run Code Online (Sandbox Code Playgroud)

c++ performance multithreading lock-free c++11

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

为什么来自非依赖基类的非限定名称比模板参数更受青睐

C++ 标准规定,来自非依赖基类的非限定名称优于模板参数。这背后的原因是什么?

以下片段来自 C++ 模板:

#include <iostream>

template <typename X>
class Base {
    public:
        int basefield;
        using T = int;
};

class D1 : public Base<Base<void>> {
    public:
        void f() { basefield = 3; // works as normal 
        }
};

template <typename T>
class D2 : public Base<double> {
    public:
        void f() { basefield = 7; }
        T strange;  // what type am I ???
};

int main() {
    D2<std::string> d;
    d.strange = 100;
}
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer

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

为什么当删除复制或移动构造函数时,命名返回值优化的 C++ 编译会失败?

我在 C++ 11/17/20/23 上的 C++ 上的 gcc 13.1 上尝试了以下操作,但是当删除移动或复制构造函数时,它无法编译。

如果未删除这些构造函数,则命名返回值优化将起作用,并且复制/移动都不会完成。

有趣的是,如果我删除名称并直接返回纯右值,那么简单的返回值优化就会起作用。

谁能对此提供解释?

#include <memory>
#include <iostream>

struct Foo{
    Foo(int v): a{v} { std::cout << "Create!\n"; }
    ~Foo() { std::cout << "Destruct!\n"; }


    Foo(const Foo&)=delete;
    Foo(Foo&&)=delete;
    
    int a;
};

// I DON'T WORK!
Foo makeFoo() {
    Foo foo{5};
    return foo;
}

// I WORK!
//Foo makeFoo() {
//    return Foo{5};
//}

int main() {
    auto foo = makeFoo();
    std::cout << "Hello world! " << foo.a << "\n";
}
Run Code Online (Sandbox Code Playgroud)

c++ return-value-optimization c++17 c++20

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