小编use*_*715的帖子

C++中高效的线程安全单例

单身类的通常模式就像

static Foo &getInst()
{
  static Foo *inst = NULL;
  if(inst == NULL)
    inst = new Foo(...);
  return *inst;    
}
Run Code Online (Sandbox Code Playgroud)

但是,我的理解是这个解决方案不是线程安全的,因为1)Foo的构造函数可能被多次调用(可能或可能不重要)和2)inst在返回到不同的线程之前可能没有完全构造.

一种解决方案是围绕整个方法包装一个互斥锁,但是在我真正需要它之后很长时间我就要付出同步开销.另一种选择是

static Foo &getInst()
{
  static Foo *inst = NULL;
  if(inst == NULL)
  {
    pthread_mutex_lock(&mutex);
    if(inst == NULL)
      inst = new Foo(...);
    pthread_mutex_unlock(&mutex);
  }
  return *inst;    
}
Run Code Online (Sandbox Code Playgroud)

这是正确的做法,还是我应该注意哪些陷阱?例如,是否存在可能发生的静态初始化顺序问题,即在第一次调用getInst时,inst总是保证为NULL?

c++ singleton pthreads thread-safety

67
推荐指数
4
解决办法
7万
查看次数

现代C++编译器的有效优化策略

我正在研究对性能至关重要的科学代码.该代码的初始版本已经编写和测试,现在,有了分析器,现在是时候从热点开始剃须周期了.

众所周知,编译器现在可以更有效地处理一些优化,例如循环展开,而不是手工编程的程序员.哪些技术还值得?显然,我会通过一个分析器来运行我尝试的所有内容,但是如果有传统的智慧关于什么往往有效,哪些无效,这将为我节省大量时间.

我知道优化非常依赖于编译器和体系结构.我正在使用针对Core 2 Duo的英特尔C++编译器,但我也对gcc或"任何现代编译器"的效果感兴趣.

以下是我正在考虑的一些具体想法:

  • 用手工卷取代STL容器/算法有什么好处?特别是,我的程序包括一个非常大的优先级队列(当前是a std::priority_queue),其操作占用了大量的总时间.这是值得研究的事情,还是STL实施可能是最快的?
  • 类似地,对于std::vector需要大小未知但上限相当小的s,用静态分配的数组替换它们是否有利可图?
  • 我发现动态内存分配通常是一个严重的瓶颈,消除它会导致显着的加速.因此,我很有兴趣通过值返回大型临时数据结构与通过指针返回相对于通过引用传递结果的性能权衡.有没有办法可靠地确定编译器是否会为给定方法使用RVO(假设调用者当然不需要修改结果)?
  • 编译器的缓存感知如何?例如,是否值得研究重新排序嵌套循环?
  • 鉴于该程序的科学性,浮点数被用于各处.我的代码中的一个重要瓶颈曾经是从浮点到整数的转换:编译器会发出代码来保存当前的舍入模式,更改它,执行转换,然后恢复旧的舍入模式---即使程序中没有任何内容永远改变了舍入模式!禁用此行为会大大加快我的代码速度.我应该注意哪些与浮点相关的类似问题?
  • C++被单独编译和链接的一个结果是编译器无法进行看起来非常简单的优化,例如在循环的终止条件下移动方法调用如strlen().有没有像我这样的优化,因为它们不能由编译器完成,必须手工完成?
  • 另一方面,我是否应该避免使用任何技术,因为它们可能会干扰编译器自动优化代码的能力?

最后,将某些类型的答案扼杀在萌芽状态:

  • 我知道优化在复杂性,可靠性和可维护性方面具有成本.对于此特定应用,提高性能值得这些成本.
  • 我知道最好的优化通常是改进高级算法,而且这已经完成了.

c++ optimization x86

45
推荐指数
6
解决办法
4233
查看次数

有没有办法在运行使用MinGW编译的程序时生成gdb可读的coredump?

我正在尝试调试一个使用MinGW的gcc编译的Windows程序,它只能 gdb 之外运行时遇到段错误(可能是一些竞争条件......可爱.)问题是,当程序崩溃并且我没有运行GDB时,我无法获得堆栈跟踪...我可以选择在MSVC崩溃时打开程序,但是MSVC无法读取gcc的调试符号,因此它给我的堆栈跟踪是没用的.

有没有办法让Windows创建一个核心转储,然后我可以在MinGW的gdb中打开?或者,有没有办法获取MSVC的堆栈跟踪(具有原始地址但没有符号)并使用gcc来获取人类可读的跟踪?

c windows gdb mingw

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

有效地确定多项式在区间[0,T]中是否有根

我有非平凡度(4+)的多项式,需要鲁棒有效地确定它们是否在区间[0,T]中有根.根的确切位置或数量与我无关,我只需要知道是否至少有一个.

现在我正在使用区间运算作为快速检查,看看我是否可以证明没有根可以存在.如果我不能,我正在使用Jenkins-Traub来解决所有多项式根.这显然是低效的,因为它检查所有真正的根并找到它们的确切位置,这些信息我最终不需要.

我应该使用标准算法吗?如果没有,在完成所有根的完整Jenkins-Traub求解之前,我还能做任何其他有效的检查吗?

例如,我可以做的一个优化是检查我的多项式f(t)在0和T处是否具有相同的符号.如果不是,则在该区间中显然存在根.如果是这样,我可以求解f'(t)的根,并在区间[0,T]中的f'的所有根处求f.当且仅当所有这些评估具有与f(0)和f(T)相同的符号时,f(t)在该区间中没有根.这减少了我必须根找到的多项式的次数.不是一个巨大的优化,但也许比没有好.

math polynomial-math numerical-methods

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

没有优先级倒置的环形缓冲区

我有一个需要将数据传递给低优先级进程的高优先级进程.我写了一个基本的环形缓冲区来处理数据的传递:

class RingBuffer {
  public:
    RingBuffer(int size);
    ~RingBuffer();

    int count() {return (size + end - start) % size;}

    void write(char *data, int bytes) {
      // some work that uses only buffer and end
      end = (end + bytes) % size;
    }

    void read(char *data, int bytes) {
      // some work that uses only buffer and start
      start = (start + bytes) % size;
    }

  private:
    char *buffer;
    const int size;
    int start, end;
};
Run Code Online (Sandbox Code Playgroud)

这是问题所在.假设低优先级进程有一个oracle,它确切地告诉它需要读取多少数据,因此count()永远不需要调用.然后(除非我遗漏了什么)没有并发问题.但是,只要低优先级线程需要调用count()(高优先级线程可能也想调用它来检查缓冲区是否太满),count()或更新中的数学可能会结束不是原子的,引入了一个bug.

我可以在访问周围放置一个互斥体来开始和结束但如果高优先级线程必须等待低优先级线程获取的锁定,那么这将导致优先级倒置. …

c++ concurrency circular-buffer

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

const成员引用的值初始化

我正在查看以下形式的代码:

class foo
{
  public:
    foo() {}

  //...
};

class bar
{
  public:
    bar() : ref() {}

  private:
    const foo &ref;
};
Run Code Online (Sandbox Code Playgroud)

是否正确使用临时初始化引用?我知道有可能初始化一个带有临时变量的局部变量的const引用,这样做可以延长临时变量的生命周期,例如:

const foo &tmp = funcThatReturnsByValue(); //OK
Run Code Online (Sandbox Code Playgroud)

但是,初始化列表中相关初始化引用的答案之一表明"短期"和"长期"引用之间存在差异,并且ref如上所述初始化是未定义的行为(即使refconst引用).

标准中的12.2.5部分地说,"在构造函数的ctor-initializer中临时绑定到引用成员,直到构造函数退出为止." 这是描述这种情况吗?

c++ reference

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

为什么将无符号的“小”整数提升为有符号的int?

该标准很明确:当对小于int的整数类型执行算术运算时,该整数会首先提升为有符号int,除非int不能代表原始类型的完整值范围,在这种情况下,提升为unsigned int

我的问题是:这项政策的动机是什么?为什么将无符号类型提升为有符号类型int,而不是总是unsigned int

当然,实际上,几乎没有什么区别,因为底层的汇编指令是相同的(只是零扩展),但是存在提升为的关键缺点signed int,而没有明显的好处,因为溢出是有符号算术中的UB,但是-用无符号算术定义。

有历史原因更喜欢签字int吗?是否存在不使用二进制补码算法的体系结构,而是将小的无符号类型提升为带符号int而不是unsigned int更容易/更快?

编辑:我认为这很明显,但是我在这里寻找事实(即解释设计决策的一些文档或参考资料),而不是“主要基于意见”的推测。

c standards

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

OpenGL:无限远点的三角形

我试图使用以下代码在OpenGL中渲染一个二维半平面:

void renderHalfplane(double *x, double *n)
{
  glPushMatrix();
  double theta = -360.0 * atan2(n[0], n[1])/(2.0*PI);

  glTranslated(x[0], x[1], 0);
  glRotated(theta, 0, 0, 1.0);

  glBegin(GL_TRIANGLES);
  glVertex4d(0.0, 0.0, 0.0, 1.0);
  glVertex4d(1.0, 0.0, 0.0, 0.0);
  glVertex4d(0.0,-1.0, 0.0, 0.0);
  glVertex4d(0.0, 0.0, 0.0, 1,0);
  glVertex4d(-1.0,0.0, 0.0, 0.0);
  glVertex4d(0.0,-1.0, 0.0, 0.0);
  glEnd();

  glPopMatrix();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我使用齐次坐标在"无限远"处绘制具有两个顶点的三角形.

这段代码在我的计算机上就像一个魅力,但是用户报告说它在他们的计算机上没有正确呈现:而不是无限的半平面,他们看到两个(有限的)三角形.

我使用w坐标0未定义的行为?它只适用于某些版本的OpenGL吗?我尝试查看Khronos OpenGL规范,但找不到一个部分,其中解析了具有w坐标0的基元的渲染.

c++ opengl

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

Python的subprocess.Popen()和source

我正在尝试调试的第三方Python 2.5脚本让我陷入困境.脚本的相关部分是:

       proc = subprocess.Popen(
               "ls && source houdini_setup",
               shell = True,
               executable = "/bin/bash",
               )
Run Code Online (Sandbox Code Playgroud)

有一个守护进程侦听端口5001并运行上面的脚本.脚本运行时,它会失败,并显示以下错误:

_cygwin.py
houdini_setup
... (more files) ...
/bin/sh: line 0: source: houdini_setup: file not found
Run Code Online (Sandbox Code Playgroud)

很多文件houdini_setup存在,如ls所示,实际上如果我在上面的脚本中将"source"更改为"cat",脚本会按预期打印houdini_setup的内容.此外,在一个真正的bash shell中运行上面的命令也可以在没有任何投诉的情况下获取文件.

有谁知道这里发生了什么?

python bash

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

在Qt中创建原始GL上下文?

我正在使用Qt进行项目.它有一些QGLWidgets,这些工作很漂亮.

问题是,我有一些遗留代码我想使用它使用原始OpenGL命令来做一些纹理和网格处理(渲染网格到图像等).我想从我的Qt代码中调用这些函数,但当然这要求我在调用OpenGL命令之前设置一个新的OpenGL上下文.

我试着做以下事情:

QGLContext context(QGLFormat::defaultFormat());
std::cout << "context creation: " << context.create() << std::endl;

if(!context.isValid())
{
    std::cout << "Cannot create GL context" << std::endl;
    return false;
}

context.makeCurrent();
callLegacyOpenGLCode();
Run Code Online (Sandbox Code Playgroud)

但它不起作用.QGLContext :: create()返回false.这是在Windows 7上使用Qt 4.8,使用OpenGL支持编译.

请问Qt为我创建一个新的OpenGL上下文是错误的方法吗?我该怎么做呢?

c++ opengl qt

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

具有不同定义的内联函数的不可预测行为

我有以下源文件:

//test1.cpp
#include <iostream>
using namespace std;

inline void foo()
{
  cout << "test1's foo" << endl;
}

void bar();

int main(int argc, char *argv[])
{
  foo();
  bar();
}
Run Code Online (Sandbox Code Playgroud)

//test2.cpp
#include <iostream>

using namespace std;

inline void foo()
{
    cout << "test2's foo" << endl;
}

void bar()
{
    foo();
}
Run Code Online (Sandbox Code Playgroud)

输出:

test1's foo
test1's foo
Run Code Online (Sandbox Code Playgroud)

咦??? 好的,所以我应该声明foos是静态的...但是这种事情不应该产生链接器错误,或者至少是警告?编译器如何从编译单元"看到"内联函数?

编辑:这是使用gcc 4.4.1.

c++ gcc

3
推荐指数
2
解决办法
479
查看次数

运算符重载和继承

我得到了以下代码:

class FibHeapNode
{
     //...

     // These all have trivial implementation
     virtual void operator =(FibHeapNode& RHS);
     virtual int  operator ==(FibHeapNode& RHS);
     virtual int  operator <(FibHeapNode& RHS);

};

class Event : public FibHeapNode
{
     // These have nontrivial implementation
     virtual void operator=(FibHeapNode& RHS);
     virtual int operator==(FibHeapNode& RHS);
     virtual int operator<(FibHeapNode& RHS);

};

class FibHeap
{
     //...

     int  DecreaseKey(FibHeapNode *theNode, FibHeapNode& NewKey)
     {
          FibHeapNode *theParent;

          // Some code

          if (theParent != NULL && *theNode < *theParent)
          {
            //...
          }

          //...
          return 1; …
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading

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

复制构造函数bug

我正在编写一个简单的nD-vector类,但遇到了一个奇怪的bug.我已经将课程剥离到最低限度,仍然可以重现该错误:

#include <iostream>

using namespace std;

template<unsigned int size> class nvector
{
public:
  nvector() {data_ = new double[size];}
  ~nvector() {delete[] data_;}

  template<unsigned int size2> 
  nvector(const nvector<size2> &other)
  {
    data_ = new double[size];
    int i=0;
    for(; i<size && i < size2; i++)
      data_[i] = other[i];

    for(; i<size; i++)
      data_[i] = 0;
  }

  double &operator[](int i) {return data_[i];}
  const double&operator[](int i) const {return data_[i];}

private:
  const nvector<size> &operator=(const nvector<size> &other); //Intentionally unimplemented for now

  double *data_;
};

int main()
{
  nvector<2> vector2d; …
Run Code Online (Sandbox Code Playgroud)

c++

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