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

C++ cli C++/CLI,“;常数;对跟踪句柄的引用,c++-cli,C++ Cli,我在代码中发现了如下内容: void foo(IList<int>^ const & list ) { ... } void foo(IList^const&list){…} 这个^const&是什么意思?我查看了C++/CLI规范,但没有找到关于持续跟踪引用的注释,也没有找到^&组合 这合法吗?它是跟踪句柄的常量引用 它允许您通过引用而不是通过值传递句柄。大概作者认为它比复制句柄更有效 如果作者想使手柄保持恒定,他应该使用以下两种方法之一 Method(TestClas

我在代码中发现了如下内容:

void foo(IList<int>^ const & list ) { ... }
void foo(IList^const&list){…}
这个
^const&
是什么意思?我查看了C++/CLI规范,但没有找到关于持续跟踪引用的注释,也没有找到
^&
组合


这合法吗?

它是跟踪句柄的常量引用

它允许您通过引用而不是通过值传递句柄。大概作者认为它比复制句柄更有效

如果作者想使手柄保持恒定,他应该使用以下两种方法之一

Method(TestClass const ^ const & parameter) 
Method(TestClass const^ parameter)
或者
方法(TestClass const^¶meter)
-但是调用方必须首先const起句柄 具有
TestClass常量^constHandle=nonstHandle

每种方法的示例如下:

// 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;
}

<>这个代码可能是由C++程序员编写的,使用普通的C++习语编写C++/CLI。这是完全错误的,只有当句柄存储在堆栈上时,才可能将引用传递给跟踪句柄。如果传递的列表引用存储在堆上对象的字段中,它将无法工作,垃圾收集器可能会移动它并使指针无效。编译器将捕获它并生成一个错误。^已经是引用,不需要其他引用

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

只要修复它,保留这样的坏代码没有什么意义:

 void foo(IList<int>^ list ) { ... }
void foo(IList^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);
    }
};
使用名称空间系统;
使用命名空间System::Collections::Generic;
参考等级测试{
公众:
IList^lst;
void foo(IList const&list){}
void wontcompile(){
foo(lst);/C3699
好吧;
傅(好);
}
};

这与
常量IList^&
相同吗?那么这种构造与仅仅通过值传递跟踪指针(
IList^
)有什么区别呢?@liori no.2-如果你像在评论中那样传递跟踪指针,它就不会得到常量。我的错误@Vulcan Eager。不一样,我得出了相似的结论。问题是,该函数位于建议我使用的外部库中。我设法在自己的代码中重新实现了它。谢谢你证实我的担心,你说得有一部分是对的。您完全可以将句柄的引用传递给托管堆。问题是不能在ref类型上使用const方法,因此c++/cli不允许您执行正确的const。运行时不会自动将某些内容强制转换为const,但如果将参数标记为const,则会与调用者形成一个协定,表示不会更改其对象。不,引用存储在哪里很重要。“Const”编码在程序集元数据的属性中,其他语言将忽略它们。@Ben,你说的“Const correct attributes”是什么意思,为什么
modopt(IsConst)
不是吗?几乎任何其他语言都不尊重它,这是另一回事…@Pavel,我的意思是C++/CLI允许您创建
const控件^
,但这样做没有用,因为即使是只读操作也不允许通过const句柄。e、 g.
myArray->size()
const std::vector*
上运行良好,但无法读取
ArrayList的
Length
属性。除了const成员函数之外,您甚至无法将两个
const System::Object^
传递给
ReferenceEquals
,因为BCL类中完全缺少正确使用const所需的属性。看起来函数希望通过引用接受其句柄,使句柄的更改在函数中可见。但是语法是可疑的,对于托管代码中的引用,您需要跟踪引用。请尝试
void foo(IList^%list)
@Ben-您肯定需要对托管堆上的对象进行跟踪引用,但是c++/cli中的堆栈语义允许您通过本机引用传递句柄,因为句柄可以保护您不被重定位。据我所知,一旦编译本机引用
IList^%
是对变量的引用,其中变量的类型为
IList^
,本机引用将最终成为跟踪引用。如果该变量存储在
ref类
中,则它可能会被垃圾收集器移动,因此使用本机引用(
IList^&
)将失败。变量的类型没有任何区别,只是变量的位置不同。值得一提的是,一些
marshall\u as
专门化了
marshall\u cppstd.h
take
System::String^const&
参数。这很烦人,因为如果我想将
String^
字段封送到
std::String
,我必须首先将其复制到堆栈中。