Where do you prefer to declare variables?

Do you like having them all in one spot at the beginning of the program, or just declaring them as you go?
- Keep them in as small of scope as possible. Avoid globals like the plague.

1
2
3
4
5
6
7
8
int foo

// bad, function works only with global 'foo'
//  function can't work with any other variable
int DoSomething()
{
  return foo + 5;
}

1
2
3
4
5
6
// good.  function can work with any variable passed to it.
//   much easier to maintian.  Less chance for error, increased reusability
int DoSomething(int foo)
{
  return foo + 5;
}


- Define variables as you need them, but refrain from putting complex types inside loops:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void func()
{
  int a = foo();
  a += bar();
  a += baz();

  // until now, we had no use for a string, but now we do:
  string b;  // but don't put it in the loop
  for(int i = 0; i < 10; ++i)
  {
    b = whatever(a);
    DoSomethingWithB(b);
  }
}
closed account (3hM2Nwbp)
It depends on how complex the problem is*, but as a rule of thumb I declare them as they as late as possible. Consider the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Not compiled might have syntax errors
#include <iostream>
int main()
{
    int choice;
    std::cin >> choice;
    ///int a, b; could be declared here, as they would be used in either control path
    if(choice == 0)
    {
        int a, b;
        std::cout << "Adding 2 Numbers\nEnter A: ";
        std::cin >> a;
        std::cout << "\nEnter B: ";
        std::cin >> b;
        std::cout << a << " + " << b << " = " << (a+b) << std::endl;
    }
    else
    {
        /// The variable 'c' will never be allocated unless the user enters a non-zero
        int a, b, c;
        std::cout << "Adding 3 Numbers\nEnter A: ";
        std::cin >> a;
        std::cout << "\nEnter B: ";
        std::cin >> b;
        std::cout << "\nEnter C: ";
        std::cin >> c;
        std::cout << a << " + " << b << " + " << c << " = " << (a+b+c) << std::endl;
    }
};
///vs
int main()
{
    int a, b, c;
    ///...
    ///...
}


* When you have to consider the life-span of objects, declaring them in the correct scope is essential.
Last edited on
A word about globals:
1
2
static Foo x[MAXFOOS];
void laser(int i);

Is x global? No. It is only accessible within this file. Any extern x declared elsewhere will not refer to this x.
Another example:
1
2
3
void laser(int i){
	extern Bar x[];
}

This x *is* global in another file, but in this file has only local extent.
^Just an FYI, using static like that is depreciated in C++ IIRC.
Ok, I asked this question because I recently made this program and think that it is really hard to read. I am trying to figure out how to make it look more readable. Maybe it looks readable already, and I'm just too new to this to read code well. I don't know. Anyways, here is the program's code, and this contains pretty much everything I've learned so far ( except structures). I didn't use any branching statements or break the thing into different functions (which would probably greatly increase readability) because I haven't gotten that far in my book yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Mad Libs.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>

int main()
{
	using std::string;
	using std::cout;
	using std::cin;
	// Variable declarations
	cout << "Enter the number of blanks that will be in this story: ";
	int blanks;
	cin >> blanks;
	cin.get();
	string * sentences = new string[blanks+1];	// stores the parts of the story
	for (int i = blanks; i >= 0; i--)		// Loop initializes strings so the next loops work
		sentences[i] = " ";
	cout << "Now enter the story. IMPORTANT: For each blank put a number, "
		<< "starting at 1 and \ncounting up.\n\n";
	int character = 0;
// These loops get the parts, stops after the last number
	for (string sentNum = "1"; character < blanks; sentNum[0]++)	
	{
		int arrayNum = 0;
		for (; sentences[character][arrayNum] != sentNum[0]; arrayNum++)
		{
			while (sentNum[0] == int('9') + 1)
				sentNum = "0";
			sentences[character] += cin.get();
		}
		character++;
	}
	for (int arrayNum = 0; sentences[character][arrayNum] != '\n'; arrayNum++)	// This loop gets the last part of their writing
		sentences[character] += cin.get();
	cout << "\n\nNow specify what type of words will go in the blanks.\n (such as color, place, noun, adjective, etc.)\n\n";
	string * blankType = new string[blanks];
	int * stringLength = new int[blanks+1];
	character = 0;
// Get the blank type and part lengths except the last part
	for (int blankNum = 1; blankNum <= blanks; blankNum++)
	{
		stringLength[character] = (sentences[character].size() - 1);
		cout << "Type for blank #" << blankNum << ": ";
		getline(cin, blankType[character]);
		character++;
	}
// Gets the last part's length, minus 2 to avoid null and newline character
	stringLength[character] = (sentences[character].size() - 2);	
	for ( int i = 0; i < 26; i++)		// Doing this to make sure the person can't see the whole story
		cout << std::endl;				// when enterning the words to be used.
// Now ask user to enter the types.  These words will be used in the finished story
	cout << "Now enter the words to fill in the blanks.\n";
	character = 0;
	string * wordsEntered = new string[blanks];
	for (int blankNum = 1; blankNum <= blanks; blankNum++, character++)
	{
		cout << blankType[character] << ": ";
		getline(cin, wordsEntered[character]);
	}
	character = 0;
// Next insert the words in place of the numbers
	for (int blankNum = 1; blankNum <= blanks; blankNum++, character++)
	{
		sentences[character].erase(stringLength[character], stringLength[character]);
		sentences[character] += wordsEntered[character];
	}
// Lastly, display the completed story
	for (int sentNum = 0; sentNum < blanks+1; sentNum++)
		cout << sentences[sentNum];
	delete[] stringLength;
	delete[] sentences;
	delete[] blankType;
	delete[] wordsEntered;
	return 0;
}


I'm still working on getting the program to accept 10 or more blanks and display it correctly. I would greatly appreciate it if you guys/girls could tell me what I have done bad and good in my formatting and things.
Functional decomposition. You needs functions.
Yes, I agree -- the reason why you think it isn't very readable is because main() does everything.

But I want to point out one thing regarding Disch's statement
Define variables as you need them, but refrain from putting complex types inside loops:

This isn't necessarily true. Consider the following functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void func1() {
    for( int i = 0; i < 10; ++i )
    {
        std::vector< std::string > v( SomeFunc() );
        DoSomethingWithIt( v );
    }
}

void func2() {
    std::vector< std::string > v;
    for( int i = 0; i < 10; ++i )
    {
        v = SomeFunc();
        DoSomethingWithIt( v );
    }
}


In func1(), each time through the loop, std::vector<>'s copy constructor is run and later its destructor is run, meaning 20 total function calls. Contrast that to func2(), in which there is 1 obvious construction, 1 obvious destruction, and 10 assignments.

But what does std::vector<>'s operator= do? First, it has to destroy all elements contained by the vector and deallocate the memory used by the vector, [/i]which is essentially the same as what the destructor does[/i], and then it has to copy the right-hand side vector to the left, which is essentially the same as what the copy constructor does.

The only difference, which in this case is nothing, is that a proper constructor would also have to set up vtables and a proper destructor would have to tear them down. However, vector<> neither inherits nor contains any virtual methods, so vector<> doesn't have a vtable.

Therefore, I can argue in the second example that the amount of work performed is equivalent to 22 function calls -- 11 copy constructors and 11 destructors -- which is actually more than what func1() does.
Topic archived. No new replies allowed.