函数中的 C++ const 参数

C++ const arguments in functions

我正在继续使用 C++ 学习 uni,并且我 运行 正在研究一些关于指针、const 参数和 class 实现的所有基础知识的严肃理解问题(它们是如此与 C++ 相比,在 Java 中很容易)

我通常使用 Java,所以 C++ 对我来说很陌生。

这是我的简单 header class "Person":

#ifndef Person_h
#define Person_h

class Person
{
private:
    char* name;
    char* adress; 
    char* phone;

public:
    Person();
    Person(char const *name, char const *adress, char const *phone);
    Person(const Person &other);
    ~Person();

    void setName(char const *name);
    char* getName() const;
    void setAdress(char const *adress);
    char* getAdress() const;
    void setPhone(char const *phone);
    char* getPhone() const;
};

#endif // !Person_h

问题就在这里。为什么我应该使用 char 指针而不是实际的 char 变量?我猜这是一些节省内存或提高性能的约定?

这就是我们教授编码的方式,并试图让我们理解指针的使用和const等。

下面是我对 class 的实现:

#include "Person.h"
//Person.h class implementation

Person::Person()
{
    Person::name = new (char[64]);
    Person::adress = new (char[64]);
    Person::phone = new (char[64]);
}

Person::Person(const char *name, const char *adress , const char *phone)
{
    Person::name = new (char[64]);
    Person::adress = new (char[64]);
    Person::phone = new (char[64]);

    setName(name);
    setAdress(adress);
    setPhone(phone);
};

Person::Person(Person const &other)
{
    Person::name = new (char[64]);
    Person::adress = new (char[64]);
    Person::phone = new (char[64]);

    setName(other.getName);
    setAdress(other.getAdress);
    setPhone(other.getPhone);
};

Person::~Person()
{
    delete [] name;
    delete [] adress;
    delete [] phone;
};

void Person::setName(const char *name)
{
    this->name = name;
};

char* Person::getName() const
{
    return name;
};

void Person::setAdress(char const *adress)
{
    this->adress = adress;
};

char* Person::getAdress() const
{
    return adress;
};

void Person::setPhone(char const *phone)
{
    this->phone = phone;
};

char* Person::getPhone() const
{
    return phone;
};

我们应该学会手动为元素分配内存,并尽量照顾整体内存管理。因此,setter 函数使用 const 参数。我想这是为了不改变元素参数?我很困惑,基本上...

而我的 IDE (MS VisualStudio 2015) 将以下行加下划线作为错误:

void Person::setName(const char *name)
{
    this->name = name;    //error
};

"a value of type 'const char *' cannot be assigned to an entity of type 'char *'"

那为什么我不能分配这些值时要使用const呢?或者我如何 "un-const" 那些,而不使成员变量本身 const?

这整件事现在对我来说只是一个很大的困惑。

编辑:我在我的考试中使用C-strings,这是为了理解我们教授的指针和内存管理。

例如

this->name = name;

有两个问题:首先是因为您试图将一种类型的变量分配给密切相关但仍然不同类型的变量。但这不是大问题。

最大的问题是您试图 重新分配 原始指针 this->name (指向您已分配的一些内存) 另一个 指针(指向其他地方)。

结果类似于

int a = 5;
int b = 10;
a = b;

然后想知道为什么 a 不再等于 5

这里有两个解决方案:第一个是继续使用指针,然后复制字符串而不是分配指针。这是通过 std::strcpy 函数完成的。

不过,我推荐的解决方案是停止对字符串使用指针,而是使用标准 C++ std::string class。然后你可以使用简单的赋值来复制字符串。它们还处理自己的内存,因此您不必担心内存泄漏、指针、释放无效指针或跟踪字符串的实际大小。

C++ 的 std::string class 与 Java String class 有一些相似之处,所以如果你来自 Java背景你应该不难调整。最大的不同是,在使用 std::string 的 C++ 中,您实际上 可以 直接将字符串与 ==.

进行比较

在现代 C++ 中,您应该仍然知道内存管理,但为了可读性、异常安全和错误,您应该使用容器,它会为您完成工作,如 std::string。

const char *name 意味着,你有一个指针,它指向一个内存部分,它本身是 const,这意味着这个内存部分中的数据不应该改变。

指针本身可以改变。

当你分配

this->name = name;

你只是将一个指针 this->name 赋给了 name 的指针。但是只有当指针是可转换类型时才能这样做。如果将 this->name 的类型从 char* 更改为类型 const char*,编译器应该不会报错。

但是在你分配任何新东西之前,你应该清理内存,例如删除[]这个->名字

通俗地说,当 name 是 const 而 this->name 是非常量时 this->name = name; 不起作用的原因是因为你的函数承诺 name 将被视为只读,但通过将此指针分配给非常量指针,您可以随意修改数据,从而违反您的承诺。

您的老师显然是在尝试用指针教您旧式 C++(本质上是面向对象的 C),因此您应该继续将 char 指针替换为字符串。如果你这样做,你的老师可能会不高兴。

我们使用 char* 而不是 char[] 的原因有很多。

  • 一个原因是效率:如果可以传递 char[],那么 char[] 的全部内容将需要复制到堆栈。当您传递 char* 时,您只是将指针复制到字符,通常是单个机器字。

  • 还有一个原因,其实是不可能的。编译器没有内置的知识,即您的 char[] 是零终止的,因此无法为其分配足够的堆栈 space 并将其复制到堆栈中。该语言的创造者宁愿不将此类内置知识放入该语言中。相反,他们决定将 char[] 隐式转换为 char*,以便在您的函数中您可以将其作为 char* 接收并使用它执行您想要的操作。

  • 另一个原因是,如果您的 char[] 有点太大,那么您的堆栈就会溢出。

因此,由于所有这些原因,当我们想要传递比机器字更大(或相当大)的类型的值时,我们不会传递值本身,而是传递指针或对它们的引用。