我想更好地了解为什么选择int结束unsigned?
就个人而言,除非有正当理由,否则我从未喜欢过签名的价值观.例如,数组中的项目数,或字符串的长度,或内存块的大小等,因此这些事情通常不可能是负面的.这样的价值没有任何意义.为什么喜欢int在所有这些情况下误导?
我问这个问题是因为Bjarne Stroustrup和Chandler Carruth都给出了建议,而int不是unsigned 在这里(约12:30').
我可以看到使用intover short或long- 的参数int是目标机器架构的"最自然"的数据宽度.
但签署无条件总是让我生气.在典型的现代CPU架构上,签名值是否真的更快?是什么让他们更好?
我试图围绕C++ 11的新习语.
似乎至少使用shared_ptr,使用new T()和之间存在实质性差异make_shared<T>().
但是重置共享指针以指向某个新实例的方法呢.以前,我通常会使用reset(new T())会员.但是,这不是因为没有首先使用make_shared()的问题吗?(即它不允许make_shared分配对象,因此它被强制将ref计数放在单独的分配中而不是与T本身相同的分配中?)
是否更好地继续使用:
mysharedptr = make_shared<T>(args...);
Run Code Online (Sandbox Code Playgroud)
或者,还有更好的方法?
并且不应该像make_shared那样重置提供参数的变量转发,这样就可以编写mysharedptr.reset(args ...);?
当用户抓住可调整大小的窗口的角落,然后移动它时,窗口首先移动窗口的内容,然后向正在调整大小的窗口发出WM_SIZE.
因此,在我想要控制各种子控件移动的对话框中,我想消除闪烁,用户首先看到Windows操作系统认为窗口看起来像什么(因为,AFAICT,操作系统使用bitblt方法移动在发送WM_SIZE之前窗口内部的东西) - 然后我的对话框才能处理移动其子控件或调整它们等等,之后它必须强制重新绘制内容,这会导致闪烁(在此处最小).
我的主要问题是:有没有办法强迫Windows不要做这个愚蠢的bitblt事情? 在窗口调整大小时移动控件的窗口或者调整其父级调整大小时,它肯定会出错.无论哪种方式,让操作系统进行预涂,只需拧紧工件即可.
我想了一段时间它可能与CS_HREDRAW和CSVREDRAW类标志有关.然而,现实是我不希望操作系统要求我擦除窗口 - 我只是想在没有操作系统的情况下重新绘制我自己的窗口内容(即我希望显示器是它的内容)在用户开始调整大小之前 - 没有来自操作系统的任何bitblit'.而且我不希望操作系统告诉每个控件它需要重绘(除非它恰好是一个实际上被调整后显示或显示的显示.
我真正想要的是:
注意:步骤2和3可以颠倒过来.
当我将DeferSetWindowPos()与标记为WS_CLIPCHILDREN的对话框资源结合使用时,上述三件事似乎正确发生.
如果我可以将上述内容用于内存DC,那么我将获得额外的小好处,然后在WM_SIZE处理程序的末尾只执行一个bitblt.
我已经玩了一段时间了,我无法逃脱两件事:
我仍然无法抑制Windows做"预测bitblt". 答案:请参阅下面的解决方案,该解决方案将覆盖WM_NCCALCSIZE以禁用此行为.
我无法看到如何构建一个对话框,其子控件绘制到双缓冲区.答案:请参阅下面的约翰答案(标记为答案),了解如何让Windows操作系统对对话框进行双重缓冲(注意:根据文档,这不允许任何GetDC()中间的绘制操作).
我的最终解决方案(谢谢所有贡献的人,尤其是John K.):
经过大量的汗水和泪水,我发现以下技术在Aero和XP或Aero禁用时都能完美运行.轻弹不存在(1).
布局代码取决于您 - 它很容易在CodeGuru或CodeProject上找到布局管理器的示例,或者自己动手.
以下是一些代码摘录,可以帮助您完成大部分工作:
LRESULT ResizeManager::WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_ENTERSIZEMOVE:
m_bResizeOrMove = true;
break;
case WM_NCCALCSIZE:
// The WM_NCCALCSIZE idea was given to me by John Knoeller:
// see: http://stackoverflow.com/questions/2165759/how-do-i-force-windows-not-to-redraw-anything-in-my-dialog-when-the-user-is-resiz
//
// The default …Run Code Online (Sandbox Code Playgroud) 解决:
*可行的解决方案:@sbi
*解释实际发生的事情:@Hans
*解释为什么OpenFile没有通过"DELETE PENDING":@Benjamin
问题:
我们的软件在很大程度上是专有脚本语言的解释器引擎.该脚本语言能够创建文件,处理文件,然后删除文件.这些都是单独的操作,并且在这些操作之间没有保持打开文件句柄.(即在文件创建过程中创建一个句柄,用于写入,然后关闭.在文件处理部分,一个单独的文件句柄打开文件,从中读取,并在EOF关闭.最后,删除使用:: DeleteFile它只使用文件名,而不是文件句柄.
最近我们开始意识到特定的宏(脚本)有时无法在随后的某个随机时间创建文件(即它在"创建,处理,删除"的前100次迭代中成功,但是当它到来时回到创建它一百零一次,Windows回复"拒绝访问").
深入研究这个问题,我编写了一个非常简单的程序,它循环遍历这样的事情:
while (true) {
HANDLE hFile = CreateFileA(pszFilename, FILE_ALL_ACCESS, FILE_SHARE_READ,
NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return OpenFailed;
const DWORD dwWrite = strlen(pszFilename);
DWORD dwWritten;
if (!WriteFile(hFile, pszFilename, dwWrite, &dwWritten, NULL) || dwWritten != dwWrite)
return WriteFailed;
if (!CloseHandle(hFile))
return CloseFailed;
if (!DeleteFileA(pszFilename))
return DeleteFailed;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这直接针对Win32 API,非常简单.我创建一个文件,写入它,关闭句柄,删除它,冲洗,重复...
但是在某些地方,我会在CreateFile()调用期间收到Access Denied(5)错误.看看sysinternal的ProcessMonitor,我可以看到底层的问题是当我试图再次创建它时,文件上有一个挂起的删除.
问题:
*有没有办法等待删除完成?
*有没有办法检测文件是否正在等待删除?
我们通过HFILE上的WaitForSingleObject()尝试了第一个选项.但是,在WaitForSingleObject执行之前,HFILE始终处于关闭状态,因此WaitForSingleObject始终返回WAIT_FAILED.显然,试图等待关闭的句柄不起作用.
我可以等待文件存在的文件夹的更改通知.但是,这似乎是一个非常开销密集的kludge只是偶尔会出现问题(也就是说:在我的Win7 x64 E6600 PC的测试中,它通常会失败迭代12000+ - 在其他机器上,它可以在迭代7或15或56或永远不会发生.
我无法识别任何明确允许此以太的CreateFile()参数.无论CreateFile有什么参数,当文件待删除时打开文件进行任何访问都是不行的.由于我可以在XP盒子和x64 Win7盒子上看到这种行为,我很确定这是微软的"按照预期"的核心NTFS行为.所以我需要一个允许操作系统在我尝试继续之前完成删除的解决方案,最好是不必要地占用CPU周期,并且没有观察该文件所在文件夹的极端开销(如果可能的话).
感谢您抽出宝贵时间阅读并发布回复.澄清问题欢迎!
[1]是的,这个循环返回写入失败或无法关闭哪个泄漏,但由于这是一个简单的控制台测试应用程序,应用程序本身退出,Windows保证所有句柄在操作系统关闭时完成.所以这里没有泄漏.
bool DeleteFileNowA(const char …Run Code Online (Sandbox Code Playgroud) 现在C++中有lambdas,我无法声明本地函数似乎真的很愚蠢......
例如:
我可以在函数体中声明一个类型,甚至可以将其初始化为值表.但我无法创建一个与该数据类型一起使用的辅助函数 - 因为我无法在函数中声明函数,并且我不能在函数外部引用该数据类型,因为它仅在该范围内可用.
有时候将数据类型从函数中拉出来很简单,并在那里定义我的数据类型和辅助函数(本地文件范围) - 但有时它并不是真正合理的解决方案 - 例如在初始化表时内联lambda引用局部范围变量(或this).
是否已经定义了对本地函数的支持是否已经定义,或者为什么编译器编写者难以实现,因此不是标准的一部分?
好的,所以我们在C++ 17,对C++中一个非常好的bitflags接口仍然没有一个令人满意的答案.
我们enum将其成员值放入封闭范围,但是隐式转换为它们的基础类型,因此可以用作 - 如果它们是位标志但拒绝重新分配回枚举而不进行转换.
我们已经enum class解决了名称范围问题,因此它们的值必须显式命名MyEnum::MyFlag或者甚至MyClass::MyEnum::MyFlag,但是它们不会隐式转换为它们的基础类型,因此不能在没有无休止地来回转换的情况下用作位标志.
最后,我们有以下的旧位域C:
struct FileFlags {
unsigned ReadOnly : 1;
unsigned Hidden : 1;
...
};
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是没有好的方法可以将自身整体化 - 人们不得不求助于使用memset或者转换地址或类似的方法来覆盖整个值或者一次初始化它或者一次操作多个位.它也无法命名给定标志的值,而不是它的地址 - 因此没有名称代表0x02,而使用枚举时有这样的名称,因此枚举命名组合时很容易标志,例如FileFlags::ReadOnly | FileFlags::Hidden- 对于比特字段来说,根本不是一个很好的方式.
此外,我们仍然有简单constexpr或#define命名位值,然后根本不使用枚举.这有效,但完全将位值与基础位标志类型分离.也许这最终不是最糟糕的方法,特别是如果位标志值constexpr在一个结构中,为它们提供自己的名称范围?
struct FileFlags {
constexpr static uint16_t ReadOnly = 0x01u;
constexpr static uint16_t Hidden = 0x02u;
...
}
Run Code Online (Sandbox Code Playgroud)
因此,就目前而言,我们有很多技术,但没有一种技术可以说是非常可靠
这是一个具有以下有效位标志的类型,它有自己的名称范围,这些位和类型应该可以与标准的按位运算符一起使用,例如| &^〜,它们应该与0之类的整数值相当,并且任何按位运算符的结果应该保持为命名类型,而不是转换为积分
所有这些都说,有很多尝试在C++中试图产生上述实体 -
DEFINE_ENUM_FLAG_OPERATORS(EnumType),然后定义运算符.&^〜以及相关的赋值操作,如| =等.enable_if元编程允许给定的枚举转换为支持缺失运算符的位标志类型,然后再静默返回.我需要一个简单的方法来获取类的对象的数量/长度/大小T这里T是某种集合类型,如中std::map,std::list,std::vector,CStringArray,CString,std::string,...
对于大多数标准类型,T::size()是正确答案,因为大多数MFC类T::GetSize()是正确的,因为CString它是T::GetLength().
我希望有一个像:
template <typename T> auto size(const T & t)
Run Code Online (Sandbox Code Playgroud)
...评估正确的成员函数调用.
看起来应该有一种简单的方法来调用一个traits模板,在T该模板上有一个size(const T & t)成员,它本身使用SFINAE存在或不存在,如果它存在,那么根据定义调用一个适当的方法t.size_function()来返回元素的数量.那个例子T.
我可以编写一个精心设计的has_member类型 - 特征模板 - 在stackoverflow上有一些例子 - 所有这些都让我觉得很复杂"必须有一个更简单的方法".使用C++ 17,似乎应该轻松优雅地解决这个问题?
这里和这里的这些讨论似乎使用了一个不优雅的解决方案,其中一些答案使用预处理器宏来完成工作.这还有必要吗?
但是......当然,必须有一种方法可以使用这样一个事实,即在a上调用正确的成员函数T是可编译的,并且调用错误的函数无法编译 - 不能直接用于创建正确的类型特征包装器给定的类型T?
我想要的是:
template <typename T>
auto size(const T & collection) …Run Code Online (Sandbox Code Playgroud) VSCode 使用许多工具进行静态代码分析和智能感知...
但是,我还没有看到如何配置应该为这些分析启用哪些构建标签?
例如,我可能有两个文件 - 一个已编译// +build debug,另一个已编译// +build !debug以启用一些仅调试代码和一些生产时代码或常量等...
但 VSCode 只是将各种内容标记为损坏,因为它尝试同时分析工作命名空间中存在的这两个文件。
当然有一种方法可以说"editor build tag" : [ "debug" ]或类似,这样静态分析和 linting 工具就不会抛出虚假的警告/问题列表。
似乎有一些虚拟文件夹与GUID相关联(控制面板,桌面) -
:: {00021400-0000-0000-c000-000000000046} //桌面
火焰是这些定义的?他们什么时候用?
我想要的是一种方法,让一个字符串代表一个没有任何歧义的虚拟文件夹.
如果,例如,我要创建一个PIDL桌面,显示名称回来为"C:\用户\史蒂夫\桌面".
嗯,目前这是真的 - 但它不是真正的正确文件夹.我可以在资源管理器中导航到该文件夹,它包含我桌面上的部分文件,而不是整个桌面.
我想是到该位置编码为一个字符串,将始终定位到虚拟桌面文件夹(即具有的所有内容,而不仅仅是几件事情之一)的方式.
有谁知道这些GUID的最终清单?或者我如何将给定的PIDL转换成一个?
我试图SHGetDisplayName(PIDL,SHGDN_*) - 的,对于桌面PIDL每一个版本给我任何短暂的"桌面"或"C:\用户\史蒂夫\桌面".(显然我是在'史蒂夫'帐户下登录的).
想法/评论/指针?
编辑:所以我似乎可以使用下面给出的答案来获得已知文件夹GUId的列表.但有没有人以编程方式知道如何从PIDL转换 - >已知文件夹GUID?我以为我可以ParseDisplayName(":: {GUID}"),以获得PIDL,但有一种方式来获得的GUID?
编辑2:我仍然找不到以编程方式获取GUID的方法.然而,我的目的,我记录CSIDL_xxx我最初用来创建对象,并编写出与后来恢复它,然后由CSIDL,它保留了正确的标识(即方式创建一个PIDL.它不不会降级为"C:\ Users \\ Desktop",而是生成一个真正指向虚拟桌面的PIDL.
我的诀窍是始终使用CSIDL-> PIDL,永远不要在它们之间使用字符串.CSIDL-> PIDL-> string-> PIDL =退化为非虚拟路径.
感谢大家的帮助 - 我会一直在寻找是否有人发现更多关于这个主题并发布它,我会感兴趣!;)
我想定义一个简单的模板函数,它接受运行时值并确定它是否是某些可能值的成员.
用法:
int x; // <- pretend this came from elsewhere...
if (isoneof(x, {5,3,9,25}) ...
Run Code Online (Sandbox Code Playgroud)
就像是:
template <typename T, size_t size>
bool isoneof(T value, T (&arr)[size])
{
for (size_t i = 0; i < size; ++i)
if (value == arr[i])
return true;
return false;
}
Run Code Online (Sandbox Code Playgroud)
我认为这注定要失败,因为我没有看到如何创建内联静态数组.
我可以用:
int kPossibilities[] = {5,3,9,25};
if (isoneodf(6, kPossibilities)) ...
Run Code Online (Sandbox Code Playgroud)
稍微改变isoneof:
template <typename T1, typename T2, size_t size>
bool isoneof(T1 value, const T2 (&arr)[size])
{
for (size_t i = 0; i < size; …Run Code Online (Sandbox Code Playgroud)