Professional Documents
Culture Documents
Int Int: J 10, K &i (J)
Int Int: J 10, K &i (J)
Page 3 of 6
ვექტორის შექმნას, რომელშიც გაასლდება მთავარ პროგრამაში შექმნილი a ვექტორი. ეს ახალი
v ვექტორი (ანუ a-ს ასლი) დაიბეჭდება, ფუნქცია დაასრულებს მუშაობას და v ვექტორი
გაუქმდება, რადგან იგი წარმოადგენს ფუნქციის ლოკალურ ცვლადს და წყვეტს არსებობას
ფუნქციის დასრულებასთან ერთად.
თუ ამ პროგრამაში გამოვიყენებთ ბეჭდვის ფუნქციას, რომელსაც პარამეტრს გადავცემთ
გადამისამართებით (რეფერენსით):
void printVector(const vector<int> &v)
{
for (auto m : v) std::cout << m << '\t';
std::cout << std::endl;
}
მაშინ ფუნქციის printVector(a); გამოძახების შედეგად არავითარი ახალი ვექტორი არ
იქმნება. უკვე არსებულ a ვექტორს დაერქმევა ახალი სახელი v, და ამიტომ v -ს ბეჭდვა ნიშნავს
a-ს ბეჭდვას. ფუნქციის დასრულების შემდეგ, a-ს ახალი სახელი (რომელიც ფუნქციის
ლოკალური ცვლადია) გაუქმდება.
როგორც ვხედავთ, პარამეტრად ვექტორის ასლის გადაწოდება ზრდის გამოყენებულ
მეხსიერებას და შესრულების დროს. ამიტომ, უპირატესობა უნდა მივანიჭოთ მეთოდებს,
რომლებიც უფრო სწრაფად და ეკონომიურად ასრულებებნ იგივე საქმეს.
მომდევნო მაგალითში, გავაკეთოთ ფუნქცია, რომელიც პარამეტრად მიიღებს ინფორმაციას
კვადრატის გვერდის შესახებ და გამოთვლის მის ფართობს და პერიმეტრს.
პირველი ვარიანტი, როდესაც პარამეტრად გადავცემთ არგუმენტის ასლს, არამარტო დროისა
და მეხსიერების თვალსაზრისით არის არახელსაყრელი, არამედ საკმაოდ რთულიცაა, რადგან
ჩვენ მოგვიწევს ვიზრუნოთ ისეთი კონტეინერის გამოყენებაზე, რომელიც ორ ნამდვილ რიცხვს
ერთდროულად შეინახავს და დაბრუნებს. ამ საკითხს ამავე ამოცანის მაგალითზე განვიხილავთ
შემდეგ პუნქტში, როდესაც ფუნქციების დასაბრუნებელ მნიშვნელობებზე უფრო დაწვრილებით
ვისაუბრებთ. რეფერენსების საშუალებით შექმნილი კოდი მარტივი გასაგებია:
void kvadrati(const double side, double &s, double &p)
{
s = side * side;
p = 4 * side;
}
int main()
{
double area, perimeter;
kvadrati(11, area, perimeter);
cout << "Side is 11, area - "
<< area << ", perimeter = " << perimeter << endl;
}
აქაც, გამოძახება
kvadrati(11, area, perimeter);
პირველ რიგში იწვევს ფუნქციის ლოკალური ცვლადების შექმნას და ინიციალიზებას:
side = 11;
double &s = area;
double &p = perimeter;
კერძოდ, area ცვლადს დაექვა მეორე სახელი s. ამის საფუძველზე, სტრიქონი
s = side * side;
იგივეა რაც
area = 11 * 11;
Page 4 of 6
მივაღწიეთ იგივე შედეგს რასაც პოინტერების შემთხვევაში.
მესამე მაგალითად შეგვიძლია განვიხილოთ ორი ცვლადის მნიშვნელობის გაცვლის ამოცანა,
რომელშიც უბრალოდ შეუძლებელია პარამეტრების ასლის გადაცემის გზით რაიმე შედეგის
მიღწევა.
<<< რეფერენსი და კლასის ობიექტი - ფუნქციის დასაბრუნებელი მნიშვნელობები
ზოგადად, ფუნქციას შეუძლია დააბრუნოს ნებისმიერი ტიპის მონაცემი, რომელიც
მისაწვდომია პროგრამისთვის. მათ შორისაა როგორც პრიმიტიული ტიპის ცვლადები (მთელი,
ნამდვილი და სხვა), ასევე სხვადასხვა კლასის ობიექტები, მათზე გადამისამართებები
(რეფერენსები), პოინტერები (იხ. შემდეგ თემებში).
პირველ მაგალითში, ჩვენ მოკლედ შევეხებით რეფერენსის დაბრუნების საკითხს. განვიხილოთ
კოდი:
void printVector(const vector< string > &v)
{
for (auto m : v) std::cout << m << '\t';
std::cout << std::endl;
}
int main()
{
vector<string> a;
string w;
cout << "Enter stirings, plz" << endl;
while(cin >> w)
a.push_back(w);
printVector(a);
cout << "a.back() = " << a.back() << endl;
a.back() = "runrunrun";
printVector(a);
} one one one litle dog run
vector კლასის მეთოდი .back()საშუალებას ^Z
გვაძლევს, რომ გავსინჯოთ და შევცვალოთ one one one litle dog run
ვექტორის ბოლო ელემენტი. ამ პროგრამის a.back() = run
one one one litle dog runrunrun
შესრულების ერთი შესაძლო ვარიანტი
Press any key to continue . . .
შემდეგია:
ეს მეთოდი (ანუ კლასის წევრი ფუნქცია) ამ შედეგს აღწევს იმის წყალობით რომ მისი
დასაბრუნებელი მნიშვნელობა გადამისამართდება დასაბრუნებელ ცვლადზე.
ვცადოთ იგივე შედეგის მიღწევა გლობალური ფუნქციის შექმნის საშუალებით:
void printVector(const vector< string > &v)
{
for (auto m : v) std::cout << m << '\t';
std::cout << std::endl;
}
string& back(vector<string> &s)
{
return s[s.size() - 1];
}
int main()
{
vector<string> a;
string w;
cout << "Enter stirings, plz" << endl;
while (cin >> w)
a.push_back(w);
printVector(a);
Page 5 of 6
cout << "a.back() = " << back(a) << endl;
back(a) = "runrunrun";
printVector(a);
}
მისი შედეგი იგივე შედეგს გვაძლევს რაც ზემოთ იყო, რადგან back(a) გადამისამართდება და
გაიგივდება a ვექტორის ბოლო ელემენტთან. გამოძახება
back(a) = "runrunrun";
აკეთებს შემდეგ საქმეს: მარჯვენა მხარეში ბრუნდება რეფერენსი ვექტორის ბოლო ელემენტზე,
ანუ მარჯვენა მხარე არის ვექტორის ბოლო ელემენტის ახალი სახელი. შედეგად, მას შეგვიძლია
მივანიჭოთ იგივე ტიპის ახალი მნიშვნელობა.
მეორე მაგალითად, განვიხილოთ საკითხი, თუ როგორ დავაბრუნებინოთ ერთ ფუნქციას ერთზე
მეტი მნიშვნელობა. მაგალითად, კვადრატის ფართობი და პერიმეტრი. აქ ერთი გამოსავალი
ასეთია: ასეთი წყვილი, შედგენილი ორი ნამდვილი რიცხვისგან, უნდა განვიხილოთ ერთ
ობიექტად. მაშინ მისი დაბრუნება შეგვიძლია return -ის საშუალებით.
ჩვენ უკვე განვიხილეთ მონაცემთა რამდენიმე ტიპი (ვექტორი, სტრინგი), რომლებიც შექმნილია
კლასის საშუალებით. C++ ენაში არის კლასი pair<ტიპი1,ტიპი2>, რომელსაც შეუძლია
დააწყვილოს ორი ობიექტი. წყვილის პირველ და მეორე ელემენტზე წვდომა ხორციელდება
სახელის და არა ინდექსის საშუალებით:
#include <iostream>
#include <vector>
using namespace std;
pair<double,double> kvadrati(double side)
{
pair<double,double> point;
point.first = side * side;
point.second = 4 * side;
return point;
}
int main()
{
auto k = kvadrati(11);
cout << "Side is 11, area - " << k.first
<< ", perimeter - " << k.second << endl;
}
შედეგი იგივეა, რაც რეფერენსის და პოინტერის გამოყენების შემთხვევაში: