【问题标题】:Convert C++ struct members from non-const to const将 C++ 结构成员从非 const 转换为 const
【发布时间】:2017-08-23 09:22:47
【问题描述】:

有没有一种简单的方法可以将非常量 C++ 结构(通过指针)传递给函数,并确保函数不能更改结构的成员?

例如:从配置文件加载结构,这要求结构是非常量的。但是随后指向结构的指针被传递给不允许更改任何内容的函数。

我已经看到通过创建结构的第二个逐字“const”副本并繁琐地复制每个成员来完成此操作。这似乎很奇怪。不过我是一名 C# 程序员,所以也许这就是在 C++ 中完成的方式...?

【问题讨论】:

  • 为什么不直接使用 const 引用作为参数:const type& argname?另一种可能是指向常量类型的指针:const type* argname,但第一种方法是常用方法。
  • "从配置文件加载结构,要求结构为非常量。" - 不对。为加载配置文件的结构实现一个构造函数,然后你可以做类似const Config config("config.txt")

标签: c++ type-conversion constants


【解决方案1】:

在 C++ 中,您可以将大对象作为引用或指针传递,这两者都称为“按引用调用”,而“按值调用”则进行复制。指针语法由 C 语言继承,与 C++ 引用不同。

要让编译器抱怨对象的更改,您必须使用 const 关键字。当然,您无论如何都可以将constness 转换为更改值,但根本不建议将constness 转换为离开。

对于以下示例,假设您有一个类 BigObject 和一个公共成员 a,它是一个整数 int

1. 引用调用(&:引用类型):

void function(const BigObject& input)
{
   int a = input.a; /* read from BigObject     */
   input.a = 42;    /* the compiler will fail! */
}

/* call that function */
BigObject input();
function(input); /* no address operator needed */

const 关键字将使引用&(不是此处的地址运算符)引用此引用无法更改的数据。如果你尝试编译器会编译失败。

2。 引用调用(*:指针类型):

void function(const BigObject* input)
{
   int a = input->a;  /* read from BigObject     */
   int b = (*input).a /* alternative to ->       */
   input->a = 42;     /* the compiler will fail! */
}

/* call that function */
BigObject input();
function(&input); /* pass address */

参数是一个指针类型,它指向不能被这个指针改变的数据。您也可以通过使用:const BigObject* const input 使指针保持不变,更多说明如下。


下面是引用和指针的区别:

  • 需要取消引用指针,这是通过取消引用(星号)operator * 或使用 -> 对类/结构成员完成的,请参见上面的代码。
  • 您还必须使用地址运算符& 传递对象的地址以获取指针。
  • 另一个区别是,引用不能是NULL,它们必须是有效的,但指针可以指向NULL

const关键字的位置:

const 关键字的位置决定了什么应该是常量,是指针还是指针指向的对象。
一般来说,如果您只是想到一条穿过*(星号)的垂直线,您会更容易记住以下内容。如果const* 的左侧,它将应用于类型(对象),如果在右侧,它将应用于指针:

                |
BigObject       *        input /* pointer to BigObject             */
const BigObject *        input /* pointer to constant BigObject    */
BigObject const *        input /* same as before, I don't use this */
BigObject       * const  input /* constant pointer to BigObject    */
                |

您也可以将它们结合起来使两者保持不变:

                |
const BigObject * const  input /* constant pointer to constant BigObject */
                |

const 关键字的位置与引用无关。 reference is always constant(这是隐式的,没有显式命名)意味着一旦设置它就不能引用另一个对象。然而,该对象是可变的。这意味着& 右侧的const 关键字将是多余的,不会改变任何东西,只是不要使用它。您应该只是在以下方面有所不同:

BigObject&        input /* reference to BigObject           */
const BigObject&  input /* reference to constant BigObject  */
BigObject const & input /* same as before, I don't use this */

【讨论】:

  • 非常清晰的回复——以及来自 Andre 的代码示例! (我现在想知道为什么我所指的原始代码使用如此冗长且容易出错的逐个成员副本。我以为我错过了一些关于 C++ 语法的内容)。我在最近的代码中看到了很多使用“&”引用,而很少使用“->”,所以安德烈关于空指针的评论也提供了一些启示。我会坚持使用“&”。考虑到语言的复杂性,很容易忽略细微差别。
  • 请注意const 的放置位置,因为放置很重要。 const BigObject * input(与 BigObject const * input 相同)表示“指向 const 对象的非 const 指针”——对象不能被修改,但指针可以。这与BigObject * const input 不同,后者表示“指向非常量对象的 const 指针”——可以修改对象,但不能修改指针。然后是BigObject const * const input(和const BigObject * const input),意思是“*a const pointer to a const object”——两者都不能修改。
  • 对于引用,const BigObject & input(与BigObject const & input 相同)不同于BigObject & const input(实际上与BigObject & input 相同)。第一个是对 const 对象的引用,所以不能修改对象,而第二个是对非 const 对象的引用,所以可以修改对象
  • @AndreKampling: const 适用于其左侧的项目,除非那里没有任何内容,否则它适用于右侧的项目。所以const BigObjectBigObject const 是一回事。 * const 表示“const 指针”,而不是“指向 const 的指针”
  • 嗨@StringTheory,如果这个或任何答案已经解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
【解决方案2】:

解决方案很简单:将指向 const 的指针传递给函数(或者,也许引用更合适)。该函数将无法通过指向 const 的指针来修改对象。

【讨论】:

    猜你喜欢
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 2017-01-18
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    相关资源
    最近更新 更多