string - C++/CX : Why doesn't returning a StringReference work like passing one as an argument?

标签 string windows-runtime c++-cx

Platform::StringReference 的存在使得您可以跨 ABI 边界将 const wchar_t* 传递给接受 String^ 的函数,而无需复印。 StringReference 隐式转换为 String^,其内部指针与原始 const wchar_t* 匹配。这是通过以下代码验证的;如果你单步执行它,你会发现pz == z:

void param(String^ s)
{
    const wchar_t* z = s->Data();
}

App::App()
{
    std::wstring p = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
    const wchar_t* pz = p.c_str();
    param(StringReference(pz));
}

但是,尝试返回 StringReference 似乎并没有以同样的方式工作,我很好奇为什么。如果我有一个返回 String^ 的函数,并且从中返回一个 StringReference,则调用相同的隐式转换运算符,但是当调用者获取其 String^ 时 它有一个不同的内部数据指针,其中包含一个副本。下面是一些尝试它的代码:

String^ ret()
{
    std::wstring s = L"12345678901234567890123456789012345678901234567890";
    const wchar_t* z = s.c_str();
    return StringReference(z);
}

App::App()
{
    String^ r = ret();
    const wchar_t* rz = r->Data();
}

该代码通过两种方式进行验证:首先,如果您单步执行,您会发现 z != rz ,其次,r 最终指向一个有效的字符串而不是垃圾,因此必须创建一个副本,因为原始字符串在 ret 末尾被释放。

我也尝试通过 out 参数返回,但得到与直接返回相同的结果(z != ozo 最终得到一个有效的字符串):

void out(String^* r)
{
    std::wstring s = L"12345678901234567890123456789012345678901234567890";
    const wchar_t* z = s.c_str();
    *r = StringReference(z);
}

App::App()
{
    String^ o;
    out(&o);
    const wchar_t* oz = o->Data();
}

是否有一种方法可以像传递 StringReference 一样跨越 ABI 边界返回 StringReference?我想该行为将取决于调用者的语言以及该语言如何从 WinRT 编码字符串,但看起来至少 C++/CX 调用者应该能够做到这一点。

最佳答案

不,您不能跨 ABI 边界返回 StringReference。跨 ABI 边界返回 StringReference 与返回局部变量的地址类似(但不相同)。这是因为 StringReference 的全部要点是 StringReference 不会分配任何新内存。

考虑一下如果您可以跨 ABI 边界返回 StringReference 会发生什么。如果你有的话会发生什么:

String^ ReturnAString()
{
    const wchar_t buffer[500] = "MyString";
    return StringReference(buffer);
}

StringReference 只是堆栈分配的缓冲区 的包装。显然,您不能跨 ABI 边界返回该值(一旦例程退出,堆栈存储就会被回收)。

相反,您需要返回一个真正的 Platform::String - Platform::String 包含字符串数据的副本,因此可以安全地将其返回给调用者。

关于string - C++/CX : Why doesn't returning a StringReference work like passing one as an argument?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17727524/

相关文章:

c++ - 从 native C++ 类的实例到 C++/CX ref 类的回调的最佳方法是什么?

c++ - 错误 C2664 'HRESULT IUnknown::QueryInterface(const IID &,void **)' : cannot convert argument 1 from 'const winrt::guid' to 'const IID &'

c# - 检查字符串是否是编译时已知的文字字符串?

windows-8 - 在嵌入式系统上以快照 View 启动应用程序

c# - 如何刷新 Metro Style 应用程序的 UI?

visual-c++ - VC++ 通过 ref 传递 Platform::String^

directx - 使用 WinRT 组件的 C# XAML Metro 应用程序在异步方法上调用 task.wait() 或 task.get() 抛出 : Unhandled exception 0xc0000409

c++ - 写入文件,编译,创建文件但不写入

java - Regex java 一个用于提取第一个字母字符的正则表达式

python - 如何使用 Python 逻辑检查回文