小编Dan*_*ger的帖子

迭代基本类型时使用const引用的任何缺点?

我发现自己最近越来越多地使用C++ 11,而且过去我会使用迭代器,我现在尽可能使用基于范围的for循环:

std::vector<int> coll(10);
std::generate(coll.begin(), coll.end(), []() { return rand(); } );
Run Code Online (Sandbox Code Playgroud)

C++ 03:

for (std::vector<int>::const_iterator it = coll.begin(); it != coll.end(); ++it) {
   foo_func(*it);
}
Run Code Online (Sandbox Code Playgroud)

C++ 11:

for (auto e : coll) { foo_func(e); }
Run Code Online (Sandbox Code Playgroud)

但是,如果集合元素类型是模板参数呢?foo_func()可能会重载以通过const引用传递复杂(=昂贵的复制)类型,并通过值传递简单的类型:

foo_func(const BigType& e) { ... };
foo_func(int e) { ... };
Run Code Online (Sandbox Code Playgroud)

当我使用上面的C++ 03风格的代码时,我没有多想.我会以相同的方式迭代,因为取消引用const_iterator会产生一个const引用,一切都很好.但是使用C++ 11基于范围的for循环,我需要使用const引用循环变量来获得相同的行为:

for (const auto& e : coll) { foo_func(e); }
Run Code Online (Sandbox Code Playgroud)

突然间我不再确定了,如果这auto是一个简单的类型(例如实现引用的幕后指针),这将不会引入不必要的汇编指令.

但是编译示例应用程序确认了简单类型没有开销,这似乎是在模板中使用基于范围的for循环的通用方法.如果不是这种情况,那么boost :: call_traits :: param_type就是这样的.

问题:标准中是否有任何保证?

(我意识到这个问题与基于范围的for循环并不真正相关.当使用const_iterators时它也存在.)

c++ templates c++11

33
推荐指数
2
解决办法
3176
查看次数

可以使用C++ 11 decltype为现有函数的函数指针创建typedef吗?

特定

struct A { 
    int foo(double a, std::string& b) const;
};
Run Code Online (Sandbox Code Playgroud)

我可以像这样创建一个成员函数指针:

typedef int (A::*PFN_FOO)(double, std::string&) const;
Run Code Online (Sandbox Code Playgroud)

很容易,但PFN_FOO如果A::foo签名发生变化则需要更新.自C++ 11引入以来decltype,它是否可以用于自动推导签名并创建typedef?

c++ decltype c++11

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

Visual C++ 2012(x86)中可能的编译器错误?

我正在使用VC++ 11(CTP Update 1)编译x86目标时遇到随机浮点错误.请参阅下面的简短示例"test.cpp",并使用以下命令进行编译:

cl /GL /O2 /EHsc test.cpp /link /MACHINE:X86
Run Code Online (Sandbox Code Playgroud)

输出应该是10 == 10,但它会10 == 0/GL(整个程序优化)启用时产生.问题似乎是get_scaling_factor()将结果推送到浮点堆栈,但调用函数期望它在SSE寄存器XMM0中.

问题:我错过了一些明显的东西,还是这真的是一个错误?当然,测试程序没有意义,因为它是一个简化的测试用例.

TEST.CPP:

#include <iostream>

template <typename T>
inline T get_scaling_factor(int units)
{
    switch (units)
    {
    case 0: return 1;  
    case 1: return 10;  
    case 2: return 100;  
    case 3: return 1000;  
    case 4: return 10000;  
    case 5: return 100000;  
    case 6: return 1000000;  
    case 7: return 10000000;  
    case 8: return 100000000; …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ compiler-bug visual-studio-2012 visual-c++-2012

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

C++中的容器协方差

我知道C++不支持容器元素的协方差,就像在Java或C#中一样.所以下面的代码可能是未定义的行为:

#include <vector>
struct A {};
struct B : A {};
std::vector<B*> test;
std::vector<A*>* foo = reinterpret_cast<std::vector<A*>*>(&test);
Run Code Online (Sandbox Code Playgroud)

毫不奇怪,我在建议这个解决另一个问题时收到了downvotes .

但是C++标准的哪一部分确切地告诉我这将导致未定义的行为?它的保证,无论std::vector<A*>std::vector<B*>他们的指针存储在内存中的continguous块.它也保证了sizeof(A*) == sizeof(B*).最后,A* a = new B完全合法.

那么我标准的标准是什么坏的(风格除外)?

c++ covariance

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

如何将64位和32位Windows Installer程序包部署为单个安装程序?

我需要部署针对Windows 64位和32位的软件设置.我为每个平台都有两个独立的Windows Installer数据库(使用WiX创建),我使用dotNetInstaller将它们组合成一个安装的bootstrapper可执行文件.

我目前正在使用dotNetInstaller的1.10版并设置auto_close_if_installed=True,因为我想完全隐藏用户的引导程序.尽管如此,dotNetInstaller坚持在我的安装程序运行时显示窗台进度条窗口,并且不会自动关闭.用户需要确认一个对话框,告诉他应用程序已成功安装.但真正的交易破坏者是它还不支持Windows 8.

升级到更高版本的dotNetInstaller似乎打破了auto_close_if_installed,所以情况更糟.

所以我的问题是:在一个可执行文件中部署这两个设置的当前技术水平是什么.Wix Burn会成为一个选择吗?

我知道在理想的世界里,我只是为我的客户提供单独的安装程序.但他们碰巧完全没有意识到这些微妙之处,他们中的大多数甚至都不知道他们正在使用什么平台.

bootstrapping windows-installer wix dotnetinstaller

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

Visual Studio:将相关的DLL复制到目标文件夹

我意识到之前已经问过这个问题 - 但是没有一个答案适用于我的具体案例:

  • 我有一个包含本机C++ EXE项目的解决方案,该项目依赖于40多个本机C++ DLL项目(在同一解决方案中).

  • EXE项目具有通常的调试,发布(和配置文件)配置,但由于它们使用相同的源代码库来构建三个不同的应用程序(例如A1,A2A3).此外,它以x32和x64为目标,因此总共有3 x 3 x 2 = 18个项目配置.

  • DLL项目由所有三个目标应用程序共享,因此只有3个(调试,发布,配置文件)时间2(x32,x64)= 6个配置.

  • 由于EXE项目依赖于DLL,因此无论何时修改,它都需要将DLL项目的相关输出复制到其目标文件夹(或其子文件夹).

你会如何处理DLL的更新?

  • 每个DLL项目中的构建后操作都不起作用(因为)它必须将DLL复制到A1,A2A3的相关输出文件夹.输出文件夹中的任何更改都会导致必须修改50个DLL项目中的每个项目中的构建后操作.

  • 我目前将DLL本身作为项目项添加到EXE项目中,并配置了自定义构建工具以将其复制到输出文件夹.但这需要我添加每个DLL 6次,所以我最终得到6 x 50 = 300个DLL!

我真正需要的是类似于复制本地选项,不幸的是只能使用程序集.您是否建议简化此构建设置?

build-process native visual-studio-2010

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

如何为同一类型提供隐式和显式转换ctr?

鉴于一个简单的template <typename T> struct X { T x, y; };,我想提供转换构造函数,以便用户可以编写:

X<double> a;
X<int16_t> b = a; // uses implicit conversion ctr (compiles with warning)
X<int16_t> c(a);  // uses explicit conversion ctr (compiles w/o warning)
X<int32_t> d = c; // uses implicit conversion ctr (compiles w/o warning)
Run Code Online (Sandbox Code Playgroud)

我相信为了实现这个目标,我需要从类型实现隐式和显式转换构造函数U.但是不可能在"隐含"上重载explicit:

template <typename T> struct X {
     X(T x = T(), T y = T()) : x(x), y(y) {}

     // implicit conversion
     template <typename U> 
     X(const X<U>& other) …
Run Code Online (Sandbox Code Playgroud)

c++ templates type-conversion c++11

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

是否可以使用std :: enable_if来选择成员模板专门化?

给出一个类声明

class A {
    template <typename T> T foo();
};
Run Code Online (Sandbox Code Playgroud)

我想专门A::foo研究各种类型(int,...)和类型类(POD,非POD)T.不幸的是,我似乎无法std::enable_if用于后者.以下内容无法编译:

template <> int A::foo<int>(); // OK

template <typename T> 
typename std::enable_if<is_pod<T>::value, T>::type foo(); // <<<< NOT OK!

template <typename T> 
typename std::enable_if<!is_pod<T>::value, T>::type foo(); // <<<< NOT OK!
Run Code Online (Sandbox Code Playgroud)

问题可能是因为这些std::enable_if<...>东西是函数签名的一部分,而且我没有在里面声明任何这样的成员A.那么如何根据类型特征专门化模板成员呢?

c++ templates template-specialization c++11

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

调试Win32应用程序挂起

我无法在Win32应用程序中找到挂起的原因.该软件以紧凑的循环将一些数据呈现给OpenGL视觉:

std::vector<uint8_t> indices;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, vertexDataBuffer);
while (...) {
    // get index type (1, 2, 4) and index count
    indices.resize(indexType * count);

    // get indices into "indices" buffer
    getIndices(indices.data(), indices.size()); //< seems to hang here!

    // draw (I'm using the correct parameters)
    glDrawElements(GL_TRIANGLES_*, count, GL_UNSIGNED_*);
}
glDisableClientState(GL_VERTEX_ARRAY);
Run Code Online (Sandbox Code Playgroud)

代码使用VC11 Update 1(CTP 3)编译.在运行优化的二进制文件时,它会getIndices()在几个循环之后挂起调用(更多关于此内容).我已经有了...

  • 三重验证了所有缓冲区,甚至是附加的CRC,以确保我没有任何缓冲区溢出
  • 在循环内添加了对HeapValidate()的调用,以确保堆没有损坏
  • 使用了ApplicationVerifier
  • 使用GFlags和PageHeap启用堆分配监控.
  • 当应用程序锁定时,它会进入WinDbg

我并没有找到该代码访问分配的缓冲区,也没有任何堆损坏任何问题.但是,如果我禁用低碎片堆,问题就会消失.如果我为indices缓冲区使用单独的(低碎片)堆,它也会消失.

无论如何,这是导致死锁的堆栈跟踪:

0:000> kb
ChildEBP RetAddr  Args to …
Run Code Online (Sandbox Code Playgroud)

c++ debugging exception-handling windbg visual-c++-2012

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

Lambda表达式:为什么没有参数类型推断?

可能重复:
C++ 0x和缺乏多态Lambda - 为什么?

C++ 0x lambda表达式支持返回类型推断到某一点.为什么参数类型也不是自动确定的?

例如,为什么我不能写:

void somefunc(const std::vector<int>& v) 
{
    std::sort(v.begin(), v.end(), [](x, y) { return x < y; });
}
Run Code Online (Sandbox Code Playgroud)

似乎编译器应该能够找出它x并且y是类型的int.

c++ lambda c++11

6
推荐指数
0
解决办法
294
查看次数