5 svar
96 visningar
Zeptuz är nöjd med hjälpen
Zeptuz 197
Postad: 13 dec 2022 15:49 Redigerad: 13 dec 2022 15:52

Vilka parameter moder skall man använda?

Har nyligen börjat med C++ så har inte jätte bra koll, men jag har fått till mig att jag tydligen har fel parameter moder samt onödiga parametrar och jag förstår inte riktigt varför. 
Jag skrev med hela min kod men det är ju egentligen bara underprogrammen som är av intresse här.
Så som jag har förstått det ska man använda const när parametern inte ska ändras, som exempelvis om en parameter är Pi och man inte vill att programmet ska kunna ändra på värdet någonstans. 
Sen så ska man väl använda & om parametern kräver mycket minne som till exempel på en string så som jag förstått det.
Sen vet jag inte riktigt när man behöver använda const och & samtidigt, men jag använder det när jag får en sträng i mina underprogram. 

#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>

using namespace std;

//Meny
void Menu_Selection(int Val)
{
  
  while(true)
    {
      cout << "1. Beräkna N-fakultet." << endl
	   << "2. Multiplicera en sträng." << endl
	   << "3. Byta värden på ett heltal och ett flyttal." << endl
	   << "4. Beräkna totala längden samt medellängden på två strängar."<< endl
	   << "5. Avsluta programmet." << endl
	   << "Val: ";
      cin >> Val;
      if ((Val < 1) or (Val > 5))
	{
	  cout << "Fel val!" << endl;
	}
      else 
	{
	  break;
	}
    }
}


//Factorial
int Calculate_Factorial(int const n)
{
  int fakultet {1};
  
  for (int i = 1; i < (n+1); i++)
    {
      fakultet = fakultet*i;
    }
  return fakultet; 
}

void Factorial_Program(int val)
{
  int n;
  
  cout << "Mata in ett heltal: ";
  cin >> n; 
  cout << "Fakulteten av " << n << " är ";
  cout << Calculate_Factorial(n) << endl;
}


//Multiplicera sträng med heltal
string Multiply(string & text,
                int const multiplier)
{
  
  string multipli{};
  
  for (int i{0}; i < multiplier; i++)
    {
      multipli = (multipli + text);
    }
  
  return multipli;
  
}

void Multiply_Program(int val)
{
  
  string text; 
  int multiplier{};
  
  cout << "Mata in en text och ett heltal: ";
  cin >> text >> multiplier;
  cout << "Den multiplicerade texten är ";
  cout << Multiply(text, multiplier) << endl; 
  
}


//Byt värde på heltal och flyttal
void Swap(int const a,
          double const b)
{
  double placeholder{b};
  b = a;
  a = static_cast<int>(ceil(placeholder));
  
}          

void Swap_Program(int val)
{
  int a {};
  double b {};
  
  cout << "Mata in ett heltal och ett flyttal: ";
  cin >> a >> b;   
  cout << "Heltalets värde är nu ";
  Swap(a, b);
  cout << a << endl;
  cout << "Flyttalets värde är nu " << fixed << setprecision(1) << b << endl; 
  
}


//Beräkna längd och meddelängd av två strängar
void Length(string const & text_1,
            string const & text_2,
            int const total_length,
            double const mean_length)
{
  total_length = text_1.length() + text_2.length();
  mean_length = static_cast<double>(total_length) / 2;
}

void Length_Program(int val)
{
  string text_1;
  string text_2;
  int total_length{};
  double mean_length{};
  
  cout << "Mata in två ord: ";
  cin >> text_1 >> text_2;
  cout << "Totallängd: ";
  Length(text_1, text_2, total_length, mean_length);
  cout << total_length << endl;
  cout << "Medellängd: " << fixed << setprecision(1) << mean_length << endl;
  
}

int main()
{
  
  int val{};
  
  cout << "Välkommen till huvudmenyn!" << endl;
  
  while(true) 
    {
      Menu_Selection(val);
      if (val == 1) 
	{
	  Factorial_Program(val);
	}
      else if(val == 2)
	{
	  Multiply_Program(val);
	}
      else if(val == 3)
	{
	  Swap_Program(val);
	}
      else if(val == 4)
	{
	  Length_Program(val);
	}
      else if(val == 5)
	{
	  break;
	}
      
    } 
  cout << "Ha en bra dag!" << endl;
  
  return 0;
}

Edit: är det kanske att jag borde lägga const i alla _Program? exempelvis Factorial_Program(int const val)

anders_k 234
Postad: 13 dec 2022 16:24 Redigerad: 13 dec 2022 16:26

Rätt eller fel i detta fall är väldigt subjektivt men så här resonerar jag:

const; jag använder det för att visa intention, så när en annan programmerare tittar på koden förstår han/hon att jag kommer inte att ändra parameter värdet i funktionen. Det är svårt att skriva tydlig kod och const är där för att hjälpa dig med det. 

När det gäller &, använd det när du skall skicka in parametrar till en funktion för stora objekt, det är lika effektivt som en pekare (vilket det egentligen är men du slipper kolla för nullptr).

När det gäller const std::string& brukar man nu förtiden säga att det är effektivare att göra move istället

Så istället för

MyClass(const std::string& foo) : m_foo{foo} {}

brukar man nu förtiden skriva för att det effektivare, man har då inte två kopior efteråt.

MyClass(std::string foo) : m_foo{std::move(foo)} {}

 

Slutligen är det lite överdrivet ovan för i de flesta fall så är inte en move/copy ovan som är avgörande när det gäller performance utan det är i 9 fall av 10 helt andra saker som arkitektur och algoritm som avgör om ett program har bra prestanda.

PS. Din if (val==1) else if borde bytas mot en switch, det är lättare att läsa.

Zeptuz 197
Postad: 13 dec 2022 16:44 Redigerad: 13 dec 2022 17:08
anders_k skrev:

Rätt eller fel i detta fall är väldigt subjektivt men så här resonerar jag:

const; jag använder det för att visa intention, så när en annan programmerare tittar på koden förstår han/hon att jag kommer inte att ändra parameter värdet i funktionen. Det är svårt att skriva tydlig kod och const är där för att hjälpa dig med det. 

När det gäller &, använd det när du skall skicka in parametrar till en funktion för stora objekt, det är lika effektivt som en pekare (vilket det egentligen är men du slipper kolla för nullptr).

När det gäller const std::string& brukar man nu förtiden säga att det är effektivare att göra move istället

Så istället för

MyClass(const std::string& foo) : m_foo{foo} {}

brukar man nu förtiden skriva för att det effektivare, man har då inte två kopior efteråt.

MyClass(std::string foo) : m_foo{std::move(foo)} {}

 

Slutligen är det lite överdrivet ovan för i de flesta fall så är inte en move/copy ovan som är avgörande när det gäller performance utan det är i 9 fall av 10 helt andra saker som arkitektur och algoritm som avgör om ett program har bra prestanda.

Tack för hjälpen, tror jag förstår det bättre nu och det där tipset med switch va jätte bra, jag visste inte att det här fanns. 
Bonusfråga: Är move i C++ som move i assembly där den kopierar innehållet i ett register och sätter in det i en annan?

 

uppdaterad kod:

#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>

using namespace std;

//Meny
int Menu_Selection()
{
  
  int val{};
   
  cout << "1. Beräkna N-fakultet." << endl
       << "2. Multiplicera en sträng." << endl
       << "3. Byta värden på ett heltal och ett flyttal." << endl
       << "4. Beräkna totala längden samt medellängden på två strängar."<< endl
       << "5. Avsluta programmet." << endl
       << "Val: ";
  cin >> val;
  if (val < 1 or val > 5)
    {
      cout << "Fel val!" << endl;
    }  
  return val;
  
}


//Factorial
int Calculate_Factorial(int & n)
{
  int fakultet {1};
  
  for (int i = 1; i < (n+1); i++)
    {
      fakultet = fakultet*i;
    }
  return fakultet; 
}

void Factorial_Program()
{
  int n;
  
  cout << "Mata in ett heltal: ";
  cin >> n; 
  cout << "Fakulteten av " << n << " är ";
  cout << Calculate_Factorial(n) << endl;
}


//Multiplicera sträng med heltal
string Multiply(string const & text,
                int & multiplier)
{
  
  string multipli{};
  
  for (int i{0}; i < multiplier; i++)
    {
      multipli = (multipli + text);
    }
  
  return multipli;
  
}

void Multiply_Program()
{
  
  string text; 
  int multiplier{};
  
  cout << "Mata in en text och ett heltal: ";
  cin >> text >> multiplier;
  cout << "Den multiplicerade texten är ";
  cout << Multiply(text, multiplier) << endl; 
  
}


//Byt värde på heltal och flyttal
void Swap(int & a,
          double & b)
{
  double placeholder{b};
  b = a;
  a = static_cast<int>(ceil(placeholder));
  
}          

void Swap_Program()
{
  int a {};
  double b {};
  
  cout << "Mata in ett heltal och ett flyttal: ";
  cin >> a >> b;   
  cout << "Heltalets värde är nu ";
  Swap(a, b);
  cout << a << endl;
  cout << "Flyttalets värde är nu " << fixed << setprecision(1) << b << endl; 
  
}


//Beräkna längd och meddelängd av två strängar
void Length(string const & text_1,
            string const & text_2,
            int & total_length,
            double & mean_length)
{
  total_length = text_1.length() + text_2.length();
  mean_length = static_cast<double>(total_length) / 2;
}

void Length_Program()
{
  string text_1;
  string text_2;
  int total_length{};
  double mean_length{};
  
  cout << "Mata in två ord: ";
  cin >> text_1 >> text_2;
  cout << "Totallängd: ";
  Length(text_1, text_2, total_length, mean_length);
  cout << total_length << endl;
  cout << "Medellängd: " << fixed << setprecision(1) << mean_length << endl;
  
}

int main()
{
  
  int val{};
  bool active = true;
  
  cout << "Välkommen till huvudmenyn!" << endl;
  
  while(active) 
    {
      val = Menu_Selection();
      switch (val)
	{
	case 1:
	    Factorial_Program();
	    break;
	case 2:
	  Multiply_Program();
	  break;
	case 3:
	  Swap_Program();
	  break;
	case 4:
	  Length_Program();
	  break;
	case 5:
	  active = false;
	  break;
	}    
    }
  
  cout << "Ha en bra dag!" << endl;
  
  return 0;
}
anders_k 234
Postad: 13 dec 2022 18:50

För att svara på din bonus fråga så råder jag dig att gå till denna site.

 

https://godbolt.org/

 

Så kan du se hur de olika kompilatorerna hanterar det.

Zeptuz 197
Postad: 13 dec 2022 18:53
anders_k skrev:

För att svara på din bonus fråga så råder jag dig att gå till denna site.

 

https://godbolt.org/

 

Så kan du se hur de olika kompilatorerna hanterar det.

Cool sida, tack!

Zeptuz 197
Postad: 14 dec 2022 01:06 Redigerad: 14 dec 2022 01:06

.

Svara Avbryt
Close