简体   繁体   English

函数中的C ++ const参数

[英]C++ const arguments in functions

I'm continuing my studies for uni with C++ and I'm running into some serious comprehension issues concerning pointers, const arguments and all the very basics of class implementations (which are so easy in Java compared to C++) 我正在继续使用C ++进行uni的学习,并且遇到了一些有关指针,const参数和类实现的所有基本知识的严重理解问题(与Java相比,在Java中如此容易)

I usually work with Java, so C++ is very new to me. 我通常使用Java,因此C ++对我来说是很新的。

This is my simple header for a class "Person": 这是我的“ 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

And here the problem starts. 问题开始了。 Why should I use char pointers instead of actual char variables? 为什么要使用char指针而不是实际的char变量? I'm guessing it's some conventions to spare memory or to improve performance? 我猜这是为了节省内存或提高性能的一些约定?

This is the way our professor codes and tries to make us understand the use of pointer and const etc. 这是我们的教授编码并试图使我们理解指针和const等用法的方式。

Now here's my implementation of the 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;
};

We should learn to manually allocate memory to elements and try to take care of the overall memory management. 我们应该学习手动为元素分配内存,并尝试照顾整个内存管理。 Therefore the use of const arguments for the setter functions. 因此,在setter函数中使用const参数。 I guess this is in order to not alter the element argument? 我猜这是为了不更改element参数? I'm very confused, basically... 我很困惑,基本上...

And my IDE (MS VisualStudio 2015) underlines the following line as error: 我的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 char *'的值分配给类型'char *'的实体”

Then why should I use const when I can't assign these values? 那么当我不能分配这些值时为什么要使用const Or how can I "un-const" those, without making the member variable itself const ? 或者,如何在不使成员变量本身为const情况下“ un-const”这些内容?

This whole matter is just one big confusion to me now. 这整个事情现在对我来说只是一个很大的困惑。

EDIT: I have to use C-strings for my exams, that's in order to understand pointer and memory management referring to our prof. 编辑:我必须在考试中使用C字符串,这是为了了解引用我们教授的指针和内存管理。

In layman's terms, the reason why this->name = name; 用外行的话来说, this->name = name;的原因this->name = name; does not work when name is const and this->name is non-const, is because your function is promising that the contents of name will be treated as read-only, but by assigning this pointer to a non-const pointer you would then be free to modify the data as you please, thus breaking your promise. name为const并且this->name为非const时不起作用,这是因为您的函数承诺将name的内容视为只读,但是通过将此指针分配给非const指针,您将可以随意修改数据,从而违背了您的诺言。

Your teacher is obviously trying to teach you old-style C++ with pointers, (essentially, object-oriented C,) so you should not go ahead and replace char pointers with strings. 你的老师明显是想教你旧式C ++的指针,(基本上,面向对象的C,),所以你应该继续和使用字符串替换字符指针。 Your teacher will probably be unhappy if you do that. 如果这样做,您的老师可能会感到不高兴。

There is a number of reasons why we use char* instead of char[] . 为什么使用char*代替char[]有很多原因。

  • One reason is efficiency: if it was possible to pass a char[] , then the entire contents of that char[] would need to be copied to the stack. 其中一个原因是效率:如果有可能通过一个char[] ,则该申请的全部内容char[]将需要被复制到堆栈。 When you pass a char* , you are only copying the pointer to the characters, which is usually a single machine word. 传递char* ,您仅将指针复制到字符,通常是单个机器字。

  • Another reason is that it is actually impossible. 另一个原因是这实际上是不可能的。 The compiler has no built-in knowledge of the fact that your char[] is zero-terminated so as to allocate enough stack space for it and copy it to the stack. 编译器不了解char[]为零终止的事实,以便为其分配足够的堆栈空间并将其复制到堆栈。 The creators of the language preferred to not put such built-in knowledge in the language. 该语言的创建者希望不要在语言中添加此类内置知识。 Instead, they decided that a char[] should be implicitly converted to char* , so that from within your function you can receive it as a char* and do what you want with it. 相反,他们决定将char[]隐式转换为char* ,以便可以从函数内部将其作为char*接收并使用它进行所需的操作。

  • Another reason is that if your char[] was just a bit too large, then your stack would overflow. 另一个原因是,如果您的char[]有点太大,那么您的堆栈就会溢出。

So, for all these reasons, when we want to pass values of types that are larger (or considerably larger) than machine words, we do not pass the values themselves, we pass pointers or references to them. 因此,由于所有这些原因,当我们要传递比机器字更大(或更大)的类型的值时,我们不传递值本身,而是传递指向它们的指针或引用。

Doing eg 做例如

this->name = name;

is problematic for two reasons: First of all because of you trying to assign a variable of one type to a variable of a closely related but still different type. 之所以会出现问题,有两个原因:首先,因为您试图将一种类型的变量分配给密切相关但仍然不同类型的变量。 But that's not the big problem. 但这不是大问题。

The big problem is that you attempt to reassign the original pointer this->name (which points to some memory you have allocated) with another pointer (which points somewhere else). 最大的问题是,您尝试用另一个指针(指向其他地方)来重新分配原始指针此- this->name (指向您已分配的内存)。

The result is similar to 结果类似于

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

and then wondering why a is no longer equal to 5 . 然后想知道为什么a不再等于5

There are two solutions here: The first one is keep using pointers and then copy the string instead of assigning pointers. 这里有两种解决方案:第一种是继续使用指针,然后复制字符串而不是分配指针。 This is done with the std::strcpy function. 这是通过std::strcpy函数完成的。

The solution I recommend though, is to stop using pointers for strings and instead use the standard C++ std::string class. 不过,我建议的解决方案是停止使用字符串指针,而使用标准C ++ std::string类。 Then you can use simple assignment to copy strings. 然后,您可以使用简单的分配来复制字符串。 They also handle their own memory, so you don't have to worry about memory leaks, pointers, freeing invalid pointers or keeping track of the actual size of the strings. 它们还处理自己的内存,因此您不必担心内存泄漏,指针,释放无效的指针或跟踪字符串的实际大小。

The std::string class of C++ shares some similarities with the Java String class, so if you come from a Java background it should not be hard for you to adjust. C ++的std::string类与Java String类具有一些相似之处,因此,如果您来自Java背景,则不难进行调整。 The biggest different is that in C++ using std::string you actually can compare strings directly with == . 最大的不同是,在C ++中使用std::string您实际上可以直接将字符串与==进行比较。

In modern C++ you should be still aware of memory management, but for the sake of readability, exception safety and bugs you should use containters, which do the work for you, as std::string. 在现代C ++中,您应该仍然了解内存管理,但是出于可读性,异常安全性和错误的考虑,应使用容器,该容器为std :: string为您工作。

const char *name means, that you have a pointer, which points to a memory section, which itself is const, which means, that the data inside this memory section shouldn't change. const char * name表示您有一个指向存储区的指针,该指针本身就是const,表示该存储区中的数据不应更改。

The pointer itself can change. 指针本身可以更改。

When you assign 分配时

this->name = name;

you are just assigning a pointer this->name to the pointer of name. 您只是将一个指针this-> name分配给name指针。 But this you can do only when the pointer are of convertible type. 但这只能在指针为可转换类型时执行。 If you change the type of this->name from char* to type const char*, the compiler shouldn't complain. 如果将this-> name的类型从char *更改为const char *,则编译器不应抱怨。

But before you assign there anything new, you should clean up the memory, eg delete[] this->name 但是在分配新内容之前,您应该清理内存,例如delete [] this-> name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM