小编Eti*_*mps的帖子

Windows上的__cdecl或__stdcall?

我目前正在开发一个Windows的C++库,它将作为DLL发布.我的目标是最大化二进制互操作性; 更确切地说,我的DLL中的函数必须可以从使用多个版本的MSVC++和MinGW编译的代码中使用,而无需重新编译DLL.但是,我对哪种调用约定是最好的cdecl或者很困惑stdcall.

有时我会听到诸如"C调用约定是唯一一个保证编译器相同的语句"的陈述,这与诸如" 解释中存在一些变化cdecl,特别是如何返回值 "之类的陈述形成对比.这似乎并没有阻止某些库开发人员(如libsndfile)在他们分发的DLL中使用C调用约定,而没有任何明显的问题.

另一方面,stdcall调用约定似乎是明确定义的.据我所知,所有Windows编译器基本上都需要遵循它,因为它是用于Win32和COM的约定.这是基于这样的假设:没有Win32/COM支持的Windows编译器不会非常有用.在论坛上发布的很多代码片段都声明了函数,stdcall但我似乎无法找到一个明确解释原因的帖子.

那里有太多相互矛盾的信息,我运行的每一次搜索都给出了不同的答案,这些答案并没有真正帮助我在两者之间作出决定.我正在寻找一个清晰,详细,有争议的解释,为什么我应该选择一个而不是另一个(或者为什么两者是等价的).

请注意,这个问题不仅适用于"经典"函数,还适用于虚拟成员函数调用,因为大多数客户端代码将通过"接口",纯虚拟类(以下描述的模式,例如此处那里)与我的DLL接口.

c++ windows dll calling-convention binary-compatibility

76
推荐指数
3
解决办法
5万
查看次数

如何编写出现在Intellisense中的C++注释?

我正在使用Visual Studio 2010 Ultimate在C++中编程.我想记录一些函数,我希望文档显示在Intellisense中.

根据MSDN,我只需要在声明之前或之后将注释放在同一行.所以我尝试了这个:

// This is a test.
void foo();
void bar() { foo(); }
Run Code Online (Sandbox Code Playgroud)

将鼠标移动时foo(),注释不会出现在工具提示中.我也尝试过:

到目前为止我没有运气.有没有人知道如何使这项工作?

c++ documentation intellisense visual-studio-2010 visual-studio

53
推荐指数
4
解决办法
5万
查看次数

如何避免C++中的连续解除分配/分配?

请考虑以下代码:

class A
{
    B* b; // an A object owns a B object

    A() : b(NULL) { } // we don't know what b will be when constructing A

    void calledVeryOften(…)
    {
        if (b)
            delete b;

        b = new B(param1, param2, param3, param4);
    }
};
Run Code Online (Sandbox Code Playgroud)

我的目标:我需要最大限度地提高性能,在这种情况下,这意味着最大限度地减少内存分配量.

这里显而易见的事情是B* b;改为B b;.我看到这种方法存在两个问题:

  • 我需要b在构造函数中初始化.由于我不知道b将会是什么,这意味着我需要将虚拟值传递给B的构造函数.哪个,IMO,很难看.
  • calledVeryOften(),我将不得不做这样的事情:b = B(…),这有两个原因:
    • 析构函数b不会被调用.
    • 将构造B的临时实例,然后将其复制到b,然后将调用临时实例的析构函数.可以避免复制和析构函数调用.更糟糕的是,调用析构函数很可能导致不良行为.

那么我必须避免使用哪些解决方案new?请记住:

  • 我只能控制A.我无法控制B,而且我无法控制A的用户.
  • 我希望尽可能保持代码的清晰和可读性.

c++ oop optimization memory-management

13
推荐指数
3
解决办法
648
查看次数

隐藏Intellisense的C++代码块

为了解决MSVC++ 2010中的一些Intellisense缺陷,我想从Intellisense"隐藏"一些代码块,而不是从编译器中"隐藏".例如:

#ifndef INTELLISENSE
void foo(); // compiled, but skipped by Intellisense
#endif
Run Code Online (Sandbox Code Playgroud)

INTELLISENSE如果这样的宏存在,我正在寻找这个宏的确切名称; 或者做同样事情的等效方法.

c++ intellisense visual-studio-2010 c-preprocessor

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

非const复制构造函数和返回值的隐式转换

考虑以下C++代码:

struct B { };
struct A
{
        A(int);
        A(A&); // missing const is intentional
        A(B);
        operator B();
};

A f()
{
        // return A(1); // compiles fine
        return 1; // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)

这在MSVC++ 2010上编译得很好(实际上,在MSVC上,如果我B完全删除它甚至可以工作).它不在GCC 4.6.0上:

conv.cpp: In function ‘A f()’:
conv.cpp:13:9: error: no matching function for call to ‘A::A(A)’
conv.cpp:13:9: note: candidates are:
conv.cpp:6:2: note: A::A(B)
conv.cpp:6:2: note:   no known conversion for argument 1 from ‘A’ to ‘B’
conv.cpp:5:2: note: A::A(A&)
conv.cpp:5:2: note:   no known conversion …
Run Code Online (Sandbox Code Playgroud)

c++ gcc copy-constructor implicit-conversion

7
推荐指数
3
解决办法
3795
查看次数

C/C++ - 将24位有符号整数转换为float

我正在用C++编程.我需要将24位有符号整数(存储在3字节数组中)转换为float(规范化为[-1.0,1.0]).

该平台是x86上的MSVC++(这意味着输入是little-endian).

我试过这个:

float convert(const unsigned char* src)
{
    int i = src[2];
    i = (i << 8) | src[1];
    i = (i << 8) | src[0];

    const float Q = 2.0 / ((1 << 24) - 1.0);

    return (i + 0.5) * Q;
}
Run Code Online (Sandbox Code Playgroud)

我不完全确定,但似乎我从这段代码得到的结果是不正确的.那么,我的代码是错的,如果是的话,为什么呢?

c c++ floating-point integer 24-bit

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

在基类中重载operator delete

从C++标准(ISO/IEC 14882:2003(E)),§12.5.4,关于重载operator delete:

如果delete-expression以unary :: operator开头,则在全局范围内查找释放函数的名称.否则,如果使用delete-expression释放静态类型具有虚拟析构函数的类对象,则释放函数是在动态类型的虚拟析构函数(12.4)的定义中通过查找找到的函数.否则,如果使用delete-expression释放类T或其数组的对象,则该对象的静态和动态类型应相同,并且在T的范围内查找解除分配函数的名称.如果此查找未能找到名称,在全局范围内查找名称.如果查找结果不明确或不可访问,或者查找选择了放置重新分配功能,则程序格式错误.

§12.5.7也很有趣:

由于成员分配和释放功能是静态的,因此它们不能是虚拟的.[注意:但是,当delete-expression的cast-expression引用类类型的对象时,因为实际调用的释放函数是在作为对象动态类型的类的范围内查找的,如果是析构函数是虚拟的,效果是一样的.例如,

struct B {
    virtual ˜B();
    void operator delete(void*, size_t);
};
struct D : B {
    void operator delete(void*);
};
void f()
{
    B* bp = new D;
    delete bp; // uses D::operator delete(void*)
}
Run Code Online (Sandbox Code Playgroud)

这里,由于虚拟析构函数,D ::非数组对象的存储由D :: operator delete()释放.

看完之后,我想知道......

  • 所有主要的C++编译器(MSVC++,GCC)都完全支持这部分标准吗?
  • 如果是这样,他们是怎么做到的?隐藏虚拟功能?"特殊"虚拟析构函调用?RTTI?
  • 使用标准中的示例:如果在单独的EXE/DLL/DSO中定义了f()和D :: operator delete(),是否会出现问题?(假设所有内容都是使用相同的编译器编译的,当然)

§5.3.5.5也可能是相关的:

在第一个替代(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.

c++ operator-overloading

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

如何在PowerShell中使用HTML Tidy .NET DLL包装器?

我正在尝试在PowerShell 2.0中使用HTML Tidy .NET包装器.

下面是一个使用C#的工作示例(包装器分发中包含的TestIt.cs):

using Tidy;
Document tdoc = new Document();
Run Code Online (Sandbox Code Playgroud)

我在PowerShell中这样做:

[Reflection.Assembly]::LoadFile("C:\Users\e-t172\Desktop\Tidy.NET\Tidy.dll")
New-Object Tidy.Document
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

New-Object : Constructor not found. Cannot find an appropriate constructor for type Tidy.Document.
At line:1 char:11
+ New-Object <<<<  Tidy.Document
    + CategoryInfo          : ObjectNotFound: (:) [New-Object], PSArgumentException
    + FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand
Run Code Online (Sandbox Code Playgroud)

附加信息:

> [Reflection.Assembly]::LoadFile("C:\Users\e-t172\Desktop\Tidy.NET\Tidy.dll").getTypes()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    ITidyDocumentEvents
True     True     TidyReportLevel                          System.Enum
True     True     __MIDL_ITidyDocument_0008                System.Enum
True     False    DocumentClass                            System.__ComObject
True     False    ITidyDocumentEvents_Event
True …
Run Code Online (Sandbox Code Playgroud)

.net windows powershell htmltidy

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