2010-08-09 40 views
8

Trong nhiều ngôn ngữ bạn được phép khai báo một biến và sử dụng nó trước khi khởi tạo nó.Lợi ích của việc cho phép biến không được khởi tạo là gì?

Ví dụ, trong C++, bạn có thể viết một đoạn như:

int x; 
cout << x; 

này sẽ đương nhiên trở khó lường (tốt, trừ khi bạn biết làm thế nào chương trình của bạn đã được lập bản đồ ra bộ nhớ) kết quả, nhưng câu hỏi của tôi là, tại sao hành vi này được phép bởi trình biên dịch?

Có một số ứng dụng hoặc hiệu quả từ việc cho phép sử dụng bộ nhớ chưa được khởi tạo không?

chỉnh sửa: Đã xảy ra với tôi rằng việc khởi tạo tối đa người dùng sẽ giảm thiểu mức ghi cho các phương tiện nhớ có tuổi thọ giới hạn (ghi chu trình). Chỉ là một ví dụ cụ thể dưới tiêu đề "hiệu suất" nói trên. Cảm ơn.

Trả lời

1

Có lẽ trong một số trường hợp, nhanh hơn để rời bộ nhớ chưa được khởi tạo cho đến khi cần thiết (ví dụ, nếu bạn trở về từ một hàm trước khi sử dụng biến). Tôi thường khởi tạo tất cả mọi thứ, tôi nghi ngờ nó làm cho bất kỳ thực sự khác nhau về hiệu suất. Trình biên dịch sẽ có cách riêng để tối ưu hóa các khởi tạo vô dụng, tôi chắc chắn.

4

Lý do lâu đời nhất trong lập trình: nó cải thiện hiệu suất!

chỉnh sửa: đọc nhận xét của bạn và tôi đồng ý - năm trước, trọng tâm về hiệu suất là số chu kỳ CPU. Trình biên dịch C đầu tiên của tôi là C truyền thống (một trước khi ANSI C) và nó cho phép tất cả các loại abominations để biên dịch. Trong những lần thực hiện hiện đại này là về số lượng khiếu nại của khách hàng. Khi tôi nói với sinh viên mới tốt nghiệp, chúng tôi thuê - 'Tôi không quan tâm chương trình đưa ra câu trả lời sai bao nhiêu'. Sử dụng tất cả các công cụ của trình biên dịch và phát triển hiện đại, viết ít lỗi hơn và mọi người có thể về nhà đúng giờ.

+2

Nó sẽ cải thiện hiệu suất nhiều hơn bằng cách thậm chí không khai báo nó? Bằng cách đó, bộ nhớ thậm chí sẽ không cần phải được cấp phát cho biến đó. Bất cứ ai trích dẫn hiệu suất cho loại mã này chỉ đơn giản là sai. –

+1

Từ khóa là * cũ nhất *. 40 năm trước khi C đã được phát triển, "lãng phí" một hoặc hai lệnh để tự động khởi tạo một biến có thể thực sự quan trọng. – dan04

+0

Làm lãng phí một hướng dẫn có thể có giá trị, nhưng theo nghĩa hiệu suất, việc có thêm hướng dẫn (hoặc hai hoặc ba) sẽ làm cho ứng dụng ít hoạt động hơn. –

1

Một số ngôn ngữ có giá trị mặc định cho một số loại biến. Điều đó đang được nói rằng tôi nghi ngờ có lợi ích hiệu suất trong bất kỳ ngôn ngữ nào để không khởi tạo chúng một cách rõ ràng. Tuy nhiên, nhược điểm là:

  • Khả năng rằng nó phải được khởi tạo và không được thực hiện bạn có nguy cơ một vụ tai nạn
  • giá trị ngoài dự kiến ​​
  • Thiếu sự rõ ràng và mục đích cho các lập trình viên khác

Đề nghị của tôi luôn khởi tạo các biến của bạn và tính nhất quán sẽ tự trả tiền.

4

Một số API được thiết kế để trả về dữ liệu thông qua các biến thông qua tại, ví dụ:

bool ok; 
int x = convert_to_int(some_string, &ok); 

Nó có thể thiết lập giá trị của 'ok' bên trong hàm, vì vậy khởi tạo nó là một sự lãng phí.

(tôi không ủng hộ phong cách này của API.)

+1

Để sử dụng "thế giới thực" này, hãy xem lớp QString của Qt: http://doc.qt.nokia.com/4.6/qstring.html#toTôi làm ví dụ. Chú ý bool * ok. – sivabudh

+0

nó phụ thuộc vào tham số chức năng cho dù chúng được nhập kiểu OUT, hoặc INOUT-typed. – YeenFei

+1

Tương tự với luồng đầu vào std: 'bool ok; std :: cin >> ok; ' – rafak

13

My suy nghĩ (và tôi đã sai trước đây, chỉ cần hỏi vợ tôi) được rằng nó chỉ đơn giản là một sự hoan lại từ thân trước đó của ngôn ngữ .

Phiên bản đầu của C không cho phép bạn khai báo biến bất kỳ nơi nào bạn muốn trong hàm, chúng phải ở trên cùng (hoặc có thể ở đầu khối, khó nhớ từ đầu của tôi kể từ khi Tôi hiếm khi làm điều đó ngày nay).

Ngoài ra, bạn có mong muốn dễ hiểu để đặt biến chỉ khi bạn biết nó nên là gì. Không có điểm trong việc khởi tạo một biến cho một cái gì đó nếu điều tiếp theo bạn sẽ làm với nó chỉ đơn giản là ghi đè lên giá trị đó (đó là nơi mà những người thực hiện đang đến từ đây).

Đó là lý do tại sao nó là cần thiết để cho phép biến uninitialised mặc dù bạn vẫn không nên sử dụng chúng trước khi bạn khởi cho họ, và trình biên dịch tốt có cảnh báo cho bạn biết về nó.

Trong C++ (và sau này là hiện thân của C) nơi bạn có thể tạo biến của mình ở bất kỳ đâu trong hàm, bạn thực sự nên tạo biến đó và khởi tạo cùng một lúc. Nhưng điều đó là không thể sớm. Bạn phải sử dụng một cái gì đó như:

int fn(void) { 
    int x, y; 
    /* Do some stuff to set y */ 
    x = y + 2; 
    /* Do some more stuff */ 
} 

Ngày nay, tôi muốn lựa chọn:

int fn(void) { 
    int y; 
    /* Do some stuff to set y */ 
    int x = y + 2; 
    /* Do some more stuff */ 
} 
+0

+1 Đến từ việc trở thành C/C++ trong nhiều năm, tôi đã thực hiện việc này. Đã gõ một trả lời dọc theo dòng này quá, bạn đánh bại tôi với nó :) Đó là khôn ngoan để khởi tạo một biến với giá trị có ý nghĩa gần với logic mã chính của bạn sử dụng nó càng tốt - khoảng cách số liệu. –

+0

@ ozmo, đây phải là câu trả lời được chấp nhận. – sivabudh

+1

+1 cho trình biên dịch hiện đại sẽ cảnh báo bạn. Chỉ cần gắn mức cảnh báo ở mức cao nhất và sau đó thực hiện tất cả các lỗi cảnh báo và bạn có tác dụng tương tự như buộc mọi người phải khởi tạo trước khi sử dụng. Chỉ vì con người là doe lười biếng không có nghĩa là chúng ta không thể bù đắp với các trình biên dịch thông minh :-) Long live hoặc compiler overlords. –

2

Câu trả lời ngắn gọn là đối với trường hợp phức tạp hơn, trình biên dịch không thể để xác định xem một biến được sử dụng trước khi khởi tạo hay không.

ví dụ:

int x; 
if (external_function() == 2) { 
    x = 42; 
} else if (another_function() == 3) { 
    x = 49; 
} 
yet_another_function(&x); 
cout << x; // Is this a use-before-definition? 

trình biên dịch tốt sẽ đưa ra một thông điệp cảnh báo nếu họ có thể nhận ra một use-trước-khởi tạo lỗi có thể xảy ra, nhưng đối với trường hợp phức tạp - đặc biệt là sự tham gia của nhiều đơn vị biên soạn - không có cách nào cho trình biên dịch để kể.

Để xem ngôn ngữ có nên cho phép khái niệm biến không được khởi tạo hay không, đó là một vấn đề khác. C# hơi khác thường khi xác định mọi biến khi được khởi tạo với giá trị mặc định. Hầu hết các ngôn ngữ (C++/C/BCPL/FORTRAN/Assembler/...) để cho lập trình viên biết liệu khởi tạo có phù hợp hay không. Trình biên dịch tốt đôi khi có thể phát hiện ra các khởi tạo không cần thiết và loại bỏ chúng, nhưng đây không phải là một sự cho phép. Các trình biên dịch cho phần cứng tối nghĩa hơn có ít nỗ lực đưa vào tối ưu hóa (đó là phần cứng của trình biên dịch viết) nên các ngôn ngữ nhắm vào phần cứng đó có xu hướng không yêu cầu tạo mã không cần thiết.

0

Tùy thuộc vào kích thước của biến, để giá trị chưa được khởi tạo trong tên hiệu suất có thể được coi là tối ưu hóa vi mô. Các chương trình tương đối ít (khi so sánh với một loạt các loại phần mềm trên mạng) sẽ bị ảnh hưởng tiêu cực bởi các chu kỳ hai hoặc ba bổ sung cần thiết để tải một đôi; Tuy nhiên, giả sử biến là khá lớn, trì hoãn khởi tạo cho đến khi nó được khởi tạo rõ ràng là cần thiết có lẽ là một ý tưởng tốt.

0

cho vòng lặp phong cách

int i; 
for(i=0;i<something;++i){ 
    ....... 
} 
do something with i 

và bạn muốn vòng lặp for để trông giống như for(init;condition;inc)

đây là một với tuyệt đối cần thiết

bool b; 
do{ 
    .... 
    b = g(); 
    .... 
}while(!b); 

màn hình ngang bất động sản với tên lồng nhau dài

phạm vi sống lâu hơn để gỡ lỗi g khả năng hiển thị

rất thỉnh thoảng hiệu suất

Các vấn đề liên quan