【问题标题】:What is the terminology for this use of a constructor?构造函数的这种使用的术语是什么?
【发布时间】:2014-07-03 19:14:38
【问题描述】:

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

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

他的代码:

BSTR someString = _bstr_t(L"Hello World");

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

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

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

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

或者我的分析完全错了......如果是这样,我很想知道


澄清:

_bstr_t is a C++ class,微软常用来包装他们的BSTR类型,所以它有构造函数/析构函数/操作符等。

BSTR 只是 WCHAR* 的 typedef,因此它没有任何逻辑。它只是一个愚蠢的指针。

【问题讨论】:

    标签: c++ constructor com bstr


    【解决方案1】:

    你是对的。

    BSTRwchar_t * 的 typedef,CComBSTR/_bstr_t 具有到 wchar_t * 的非常量转换运算符。

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

    你可以使用

    _bstr_t someString ("Hello World");
    

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

    【讨论】:

    • 很高兴您同意。我的问题是“范围”。我通常认为对象的范围是括号到括号的;从{ 直到匹配的}。但是这里没有括号......那么究竟是什么定义了临时_bstr_t的“范围”?
    • @abelenky:我不是语言律师——也许你可以在这里问这个确切的问题,人们会很乐意回答的。我确定的是在赋值之后调用了析构函数。与 const _bstr_t& someString = "Hello, World" 对比,后者调用复制构造函数,其范围由括号分隔。
    【解决方案2】:

    有问题的代码

     BSTR someString = _bstr_t(L"Hello World");
    

    正在做一个conversion constructor call,它使用传递的wchar_t[] 创建一个bstr_t 实例。这本身就很好。例如,如果您想调用一个接受BSTR 的函数并在其中传递一个字符串文字,您可以轻松地做到这一点:

    someFunction( _bstr_t(L"Hello World") ); // OKAY
    

    这没关系,因为临时文件将继续存在直到整个语句结束结束分号所在的位置(这就是 C++ 临时文件的工作方式)。

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

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

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

     _bstr_t someString(L"Hello World");
    

    【讨论】:

    • 谢谢,“转换构造函数”这个词正是我要找的。​​span>
    猜你喜欢
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多