C++/CLI,“常数”对跟踪句柄的引用

发布于 2024-08-31 23:13:01 字数 235 浏览 1 评论 0原文

我在代码中发现了类似的内容:

void foo(IList<int>^ const & list ) { ... }

What does this ^ const& Mean?我查看了 C++/CLI 规范,但没有找到关于进行持续跟踪引用的注释,也没有找到 ^& 组合。

这合法吗?

I have spotted something like this in code:

void foo(IList<int>^ const & list ) { ... }

What does this ^ const& mean? I looked in the C++/CLI specification, but found no comments on making constant tracking references, nor the ^& combo.

Is this legal?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冧九 2024-09-07 23:13:02

它是跟踪手柄的常量参考。

它允许您通过引用而不是通过值传递句柄。想必作者认为比复制句柄效率更高。

如果作者打算使句柄保持不变,他应该使用

Method(TestClass const ^ const & parameter) 
Method(TestClass const^ parameter)

或者
Method(TestClass const^¶meter) - 但调用者必须先const up句柄

TestClass const^ constHandle = nonConstHandle

每个示例:

// test.cpp : Defines the entry point for the console application.

#include "stdafx.h"

ref class TestClass
{
public:

    void setA(int value)
    {
        a = value;
    }

    TestClass() : 
        a(10)
    {
    }

private:    
    int a;
};

class TakesHandle
{
public:

    void methodX1(TestClass const ^ const & parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }

    void methodX2(TestClass const^ parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }

    void methodX3(TestClass const^& parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    TakesHandle takes;
    TestClass ^ test1 = gcnew TestClass();

    // compiles
    takes.methodX1(test1);

    // compiles
    takes.methodX2(test1);

    TestClass const ^ constHandle = test1;
    takes.methodX3(constHandle);

    return 0;
}

It's a reference which is constant to a tracking handle.

It allows you to pass the handle by reference instead of by value. Presumably the author thinks it's more efficient than copying the handle.

If the author meant to make the handle constant he should have used either of

Method(TestClass const ^ const & parameter) 
Method(TestClass const^ parameter)

Or alternatively
Method(TestClass const^& parameter) - but the caller must const up the handle first
with
TestClass const^ constHandle = nonConstHandle

An example of each:

// test.cpp : Defines the entry point for the console application.

#include "stdafx.h"

ref class TestClass
{
public:

    void setA(int value)
    {
        a = value;
    }

    TestClass() : 
        a(10)
    {
    }

private:    
    int a;
};

class TakesHandle
{
public:

    void methodX1(TestClass const ^ const & parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }

    void methodX2(TestClass const^ parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }

    void methodX3(TestClass const^& parameter)
    {
    // Un-commenting below causes compiler error
    // parameter->setA(11);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    TakesHandle takes;
    TestClass ^ test1 = gcnew TestClass();

    // compiles
    takes.methodX1(test1);

    // compiles
    takes.methodX2(test1);

    TestClass const ^ constHandle = test1;
    takes.methodX3(constHandle);

    return 0;
}
冷月断魂刀 2024-09-07 23:13:01

这段代码可能是由 C++ 程序员编写的,他使用常见的 C++ 习惯用法来编写 C++/CLI。这是完全错误的,只有当句柄存储在堆栈上时才可以传递对跟踪句柄的引用。如果传递的 List<> 则无法工作。引用存储在堆上对象的字段中,垃圾收集器可以移动它并使指针无效。编译器会捕获它并生成错误。 ^ 已经是参考,不需要额外的参考。

如果没有引用,const 关键字也不再有多大意义。以前从未这样做过,CLR 无法强制执行它。这在这里并不重要,无法从任何其他 .NET 语言调用此代码。它们不会生成指向跟踪句柄的指针。

只需修复它即可,保留这样的错误代码没有什么意义:

 void foo(IList<int>^ list ) { ... }

显示引用无法工作的代码示例:

using namespace System;
using namespace System::Collections::Generic;

ref class Test {
public:
    IList<int>^ lst;
    void foo(IList<int> const &list) {}
    void wontcompile() {
        foo(lst);  // C3699
        IList<int>^ okay;
        foo(okay);
    }
};

This code was probably written by a C++ programmer that used common C++ idiom to write C++/CLI. It is quite wrong, passing a reference to tracking handle is only possible if the handle is stored on the stack. It cannot work if the passed List<> reference is stored in a field of an object on the heap, the garbage collector can move it and make the pointer invalid. The compiler will catch it and generate an error. The ^ is already a reference, no additional reference is needed.

Without the reference, the const keyword doesn't make a lot of sense anymore either. Not that it ever did before, the CLR cannot enforce it. Not that this mattered much here, this code could not be called from any other .NET language. They won't generate a pointer to the tracking handle.

Just fix it, there's little point in keeping bad code like this:

 void foo(IList<int>^ list ) { ... }

Example of code that shows that the reference cannot work:

using namespace System;
using namespace System::Collections::Generic;

ref class Test {
public:
    IList<int>^ lst;
    void foo(IList<int> const &list) {}
    void wontcompile() {
        foo(lst);  // C3699
        IList<int>^ okay;
        foo(okay);
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文