01/10/2018, 11:22

Con trỏ hằng trong hàm

#include <iostream>
using namespace std;
void f(int *x) {
	int a = 4;
	x = &a;
}
void g(int *&x) {
	int a = 3;
	x = &a;
}
void h(const int *&x) {
	int b = 2;
	x = &b;
}
int main() {
	int *p = new int;
	*p = 5;
	f(p);
	cout << p << " " << *p << endl; // Print #1
	g(p);
	cout << p << " " << *p << endl; // Print #2  chỗ này em không hiểu ạ?
	cout << p << " " << *p << endl; // Print #3  chỗ này em không hiểu ạ?
	const int*p1 = p;
	h(p1);
	cout << p << " " << *p << endl; // Print #4  chỗ này em không hiểu ạ?
	cout << p << " " << *p << endl; // Print #5  chỗ này em không hiểu ạ?
	system("pause");
	return 0;
}
rogp10 viết 13:38 ngày 01/10/2018

Về đọc lại đi bạn hàm h mới là nhức não, thử thay tham chiếu bằng biến bt xem.

nguyen phuong vuong viết 13:24 ngày 01/10/2018

@rogp10 Mình có tìm hiểu rồi mà vẫn không hiểu sao *p tại Print #3 và Print #5 lại thay đổi thành giá trị khác nữa.

Lê Tuấn Anh viết 13:38 ngày 01/10/2018

const int*p1 = p;

Đây là con trỏ hằng, sẽ không thay đổi giá trị bằng cách dùng chính nó (vd: *p1 = 2), nhưng ta có thể thay đổi địa chỉ nơi con trỏ trỏ đến như trong hàm h thực hiện.

void h(const int *&x) {
int b = 2;
x = &b;
}

=> Giá trị của con trỏ sẽ được thay đổi.

nguyen phuong vuong viết 13:37 ngày 01/10/2018

@anhLT nếu là con trỏ hằng thì *p của print#4 và print#5 lại thay đổi mà giá trị con trỏ p trỏ đến lại không hề thay đổi --> mình chưa hiểu rõ lắm.

Lê Tuấn Anh viết 13:33 ngày 01/10/2018

khi khai báo và khởi tạo con trỏ p1 như chương trình, địa chỉ của p1 chính là p và khi p1 thay đỏi thì p cũng thay đổi thôi.

const int*p1 = p;
h(p1);

nguyen phuong vuong viết 13:28 ngày 01/10/2018

cout << p << " " << *p << endl; // Print #4 chỗ này em không hiểu ạ?
cout << p << " " << *p << endl; // Print #5 chỗ này em không hiểu ạ?

@anhLT Mình nghĩ nó thay đổi thì đúng rồi nhưng ở hàng 2 cũng giống vậy mà *p lại nhận 1 giá trị khác á

Lê Tuấn Anh viết 13:29 ngày 01/10/2018

Sao lại khác nhau được nhỉ, output của bạn ra ntn?
Của mình thì giống nhau.

nguyen phuong vuong viết 13:24 ngày 01/10/2018

Mình xài visual studio 2017 á, cậu chạy linux phải không

Lê Tuấn Anh viết 13:25 ngày 01/10/2018

Mình chạy lại trên VS thì cũng ra kết quả tương tự của bạn. Có sự khác biệt.
Mình có xem lại code, phát hiện ra cái này:

void g(int *&x) {
int a = 3;
x = &a;
}
void h(const int *&x) {
int b = 2;
x = &b;
}

Hai hàm này đang gán địa chỉ của tham số đầu với địa chỉ của một biến local.(a, b)
Việc này gây ra hậu quả là sau khi thoát khỏi hàm, các biến local sẽ bị giải phóng(mất địa chỉ) => biến con trỏ sẽ trỏ đến 1 địa chỉ không biết trước được.
=> Đây là 1 trong các nguyên nhân gây ra tình trạng memory leak

Bạn thử lại bằng cách thay biến local bằng global xem, kết quả sẽ đúng như mong đợi.

viết 13:34 ngày 01/10/2018

ko phải là memory leak mà là dangling pointer, hay pointer trỏ tới vùng nhớ đã được giải phóng, khác với memory leak là “mất dấu” vùng nhớ ko được giải phóng tự động

stackoverflow.com
code muncher

What is a dangling pointer?

c++, dangling-pointer
asked by code muncher on 02:45PM - 01 Aug 13
Lê Tuấn Anh viết 13:38 ngày 01/10/2018

Trong trường hợp này là cấp phát động mà bạn.

Memory leaks happen when your program loses the address of some bit of dynamically allocated memory before giving it back to the operating system
Memory leaks can result from a pointer going out of scope.

Còn cái dangling pointer là do deallocate memory.
A pointer that is pointing to deallocated memory is called a dangling pointer

Mình trích dẫn từ nguồn này: http://www.learncpp.com/cpp-tutorial/69-dynamic-memory-allocation-with-new-and-delete/

viết 13:33 ngày 01/10/2018

cấp phát tự động trên stack vẫn được tính là dangling pointer. Đọc cái trả lời ở dưới đi.

int* f()
{
    int a;
    return &a;
}

định nghĩa là “A pointer that is pointing to deallocated memory is called a dangling pointer”, vậy sau khi thoát f() thì a có được giải phóng ko? Nếu được thì &a có được gọi là dangling pointer ko?

Lê Tuấn Anh viết 13:29 ngày 01/10/2018

uh, đúng rồi, là dangling pointer. Thank you!

Bài liên quan
0