使用构造函数的术语是什么?

abe*_*nky 5 c++ com constructor bstr

一位同事编写了以下代码,我确信这是错误的.

我想向他解释问题,但不知道正确的术语,所以我找不到支持我的立场的参考资料:

他的代码:

BSTR someString = _bstr_t(L"Hello World");
Run Code Online (Sandbox Code Playgroud)

为什么我认为它是错误的:
我相信它会_bstr_t(L"Hello World");调用构造函数_bstr_t,并创建一个该类型的短期临时变量.在该行代码之后(在分号序列点之后),该临时符将被自动删除,并且其字符串空间被释放.
这将someString指向已释放的内存.

问题:
构造函数调用的正确术语是什么?

你能指出一些描述使用细节的参考/术语/页面吗?

临时_bstr_t对象有术语吗?
我想我会称之为"匿名,临时变量",但我不知道这在技术上是否准确.

(或者在我的分析中我可能完全错了......如果是的话,我很想知道)


为了澄清:

_bstr_t是一个C++类,Microsoft通常用它来包装它们的BSTR类型,所以它有构造函数/析构函数/运算符等.

BSTR是一个只有a的typedef WCHAR*,所以它没有任何逻辑.它只是一个愚蠢的指针.

Ale*_* C. 5

你是对的.

A BSTR是一个typedef wchar_t *,并且CComBSTR/_bstr_t有一个非const转换运算符wchar_t *.

因此,_bstr_t分配临时,someString通过转换运算符分配指向其开头的指针,并在对象超出范围时释放该对象.然后你得到一个悬垂的指针.

您可以使用

_bstr_t someString ("Hello World");
Run Code Online (Sandbox Code Playgroud)

相反,甚至_bstr_t someString = "Hello, World";.

  • @abelenky:我不是语言律师 - 也许你可以在这里问这个确切的问题,人们会乐意回答.我确定的是,在赋值后调用析构函数.与`const _bstr_t&someString ="Hello,World"相反,它调用复制构造函数,其范围由括号分隔. (2认同)

sha*_*oth 3

有问题的代码

 BSTR someString = _bstr_t(L"Hello World");
Run Code Online (Sandbox Code Playgroud)

正在执行转换构造函数调用,该bstr_t调用使用传递的wchar_t[]. 这本身就很好。例如,如果您想调用一个函数接受BSTR并传递一个字符串文字,您可以轻松地执行此操作:

someFunction( _bstr_t(L"Hello World") ); // OKAY
Run Code Online (Sandbox Code Playgroud)

这没问题,因为临时变量会一直存在,直到整个语句结束,以分号所在的位置结束(这就是 C++ 临时变量的工作方式)。

然而,有问题的代码是不行的,因为该_bstr_t实例随后用于实例化一个BSTR实例(使用 class 中的转换运算符bstr_t),该实例的寿命比临时值长(临时值在分号处被销毁,而BSTR指针的someString寿命远远超出了该值)。所以你会得到一个悬空BSTR指针someString,使用它会导致未定义的行为。如果 OLE 堆选择保留用于映射到进程地址空间的字符串的内存,它甚至可能看起来可以工作。

class _bstr_t随实现一起提供(Windows SDK 中的文件 comutil.h),因此您可以使用调试器单步执行代码,并看到SysAllocString()创建临时文件时有一个调用,然后在SysFreeString()销毁临时文件时有一个调用,而后者发生在代码之前继续到下一行。因此,在代码进入下一行之前,OLE 堆中的字符串对象被释放,并且someString指针在相关代码之后立即悬空。我想这足以让最持怀疑态度的人相信。

所以是的,你是对的,代码是错误的。正确的代码是:

 _bstr_t someString(L"Hello World");
Run Code Online (Sandbox Code Playgroud)