Wednesday, July 31, 2013

C++中值传递、指针传递和引用传递的比较

C++中值传递、指针传递和引用传递的比较

from:  http://blog.csdn.net/jimmy54/article/details/4748928
 C++引用与指针的比较

引用是C++中的概念,初学者容易把引用和指针混淆一起。
一下程序中,n是m的一个引用(reference),m是被引用物(referent)。
int m;
int &n = m;
n相当于m的别名(绰号),对n的任何操作就是对m的操作。
所以n既不是m的拷贝,也不是指向m的指针,其实n就是m它自己。

引用的规则:

(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

以下示例程序中,k被初始化为i的引用。
语句k = j并不能将k修改成为j的引用,只是把k的值改变成为6。
由于k是i的引用,所以i的值也变成了6。
int i = 5;
int j = 6;
int &k = i;
k = j; // k和i的值都变成了6;

引用的主要功能是传递函数的参数和返回值。

C++语言中,函数的参数和返回值的传递方式有三种:
值传递、指针传递和引用传递。


以下是"值传递"的示例程序。

由于Func1函数体内的x是外部变量n的一份拷贝,改变x的值不会影响n, 所以n的值仍然是0。
void Func1(int x)
{
x = x + 10;
}
...
int n = 0;
Func1(n);
cout << "n = " << n << endl; // n = 0

以下是"指针传递"的示例程序。

由于Func2函数体内的x是指向外部变量n的指针,改变该指针的内容将导致n的值改变,所以n的值成为10。
void Func2(int *x)
{
(* x) = (* x) + 10;
}
...
int n = 0;
Func2(&n);
cout << "n = " << n << endl; // n = 10

以下是"引用传递"的示例程序。

由于Func3函数体内的x是外部变量n的引用,x和n是同一个东西,改变x等于改变n,所以n的值成为10。
void Func3(int &x) {
x = x + 10;
}
...
int n = 0;
Func3(n); cout << "n = " << n << endl; // n = 10

对比上述三个示例程序,会发现"引用传递"的性质象"指针传递",而书写方式象"值传递"。

Monday, July 29, 2013

Thursday, July 25, 2013

c++ extern

From:http://www.gamedev.net/page/resources/_/technical/general-programming/organizing-code-files-in-c-and-c-r1798

When the linker comes to create an executable (or library) from your code, it takes all the object (.obj or .o) files, one per translation unit, and puts them together. The linker's main job is to resolve identifiers (basically, variables or functions names) to machine addresses in the file. This is what links the various object files together. The problem arises when the linker finds two or more instances of that identifier in the object files, as then it cannot determine which is the 'correct' one to use. The identifier should be unique to avoid any such ambiguity. So how come the compiler doesn't see an identifier as being duplicated, yet the linker does?

Imagine the following code:

/* Header.h */
#ifndef INC_HEADER_H
#define INC_HEADER_H
int my_global;
#endif /* INC_HEADER_H */

/* code1.cpp */
#include "header1.h"
void DoSomething()
{
 ++my_global;
}

/* code2.cpp */
#include "header1.h"
void DoSomethingElse()
{
 --my_global;
}
 
This first gets compiled into two object files, probably called 
code1.obj and code2.obj. Remember that a translation unit contains full 
copies of all the headers included by the file you are compiling. 
Finally, the object files are combined to produce the final file.
 
Notice how there are two copies of "my_global" in that final block. 
Although "my_global" was unique for each translation unit (this would be
 assured by the use of the inclusion guards), combining the object files
 generated from each translation unit would result in there being more 
than one instance of my_global in the file. This is flagged as an error,
 as the linker has no way of knowing whether these two identifiers are 
actually  same one, or if one of them was just misnamed and they were 
actually supposed to be 2 separate variables. So you have to fix it.

The
 answer is not to define variables or functions in headers. Instead, you
 define them in the source files where you can be sure that they will 
only get compiled once (assuming you don't ever #include any source 
files, which is a bad idea for exactly this reason). This gives you a 
new problem: how do you make the functions and variables globally 
visible if they aren't in a common header any more? How will other files
 "see" them? The answer is to declare the functions and variables in the
 header, but not to define them. This lets the compiler know that the 
function or variable exists, but delegates the act of resolving the 
address to the linker.  

To do this for a variable, you add the keyword 'extern' before its name:
extern int my_global;The 'extern' specifier is like telling the compiler to wait until link time to resolve the 'connection'. And for a function, you just put the function prototype:

int SomeFunction(int parameter);Functions are considered 'extern' by default so it is customary to omit the 'extern' in a function prototype.

Of course, these are just declarations that my_global and SomeFunction exist somewhere. It doesn't actually create them. You still have to do this in one of the source files, as otherwise you will see a new linker error when it finds it cannot resolve one of the identifiers to an actual address. So for this example, you would add "int my_global" to either Code1.cpp or Code2.cpp, and everything should work fine. If it was a function, you'd add the function including its body (ie. the code of the function) into one of the source files.

The rule here is to remember that header files define an interface, not an implementation. They specify which functions, variables, and objects exist, but it is not responsible for creating them. They may say what a struct or class must contain, but it shouldn't actually create any instances of that struct or class. They can specify what parameters a function takes and what it returns, but not how it gets the result. And so on. This is why the list of what can go into a header file earlier in this article is important.
 

Tuesday, July 23, 2013

Eclipse+CDT

Two days of work, finally makes it work for Eclipse+CDT。
If you want to use your own makefile, create new project -> c++ project -> Makefile Project -> empty project.

If you want to debug, you need to compile with g++ -g in makefile.

When you debug in Eclipse, if something is wrong, it can be show in the Console, choose gdb or gdb traces view.

In the trace, you will know where is the error: such as:

058,863 306^done,stack=[frame={level="0",addr="0x000000000040593e",func="std::vector<std::vector<dou\
ble, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::size\
",file="/usr/include/c++/4.6/bits/stl_vector.h",fullname="/usr/include/c++/4.6/bits/stl_vector.h",li\
ne="571"},frame={level="1",addr="0x000000000040506e",func="std::vector<std::vector<double, std::allo\
cator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::vector",file="/usr\
/include/c++/4.6/bits/stl_vector.h",fullname="/usr/include/c++/4.6/bits/stl_vector.h",line="279"},fr\
ame={level="2",addr="0x0000000000404b21",func="NodeVector::getVector",file="NodeVector.h",fullname="\
/home/ying/study/SocialNetwork/ConstParse/SVMKernelCV2/NodeVector.h",line="32"},frame={level="3",add\
r="0x0000000000413d62",func="compute_matrices_for_optimization",file="svm_learn.cpp",fullname="/home\
/ying/study/SocialNetwork/ConstParse/SVMKernelCV2/svm_learn.cpp",line="1967"},frame={level="4",addr=\
"0x0000000000413a6b",func="optimize_svm",file="svm_learn.cpp",fullname="/home/ying/study/SocialNetwo\
rk/ConstParse/SVMKernelCV2/svm_learn.cpp",line="1900"},frame={level="5",addr="0x0000000000412a5f",fu\
nc="optimize_to_convergence",file="svm_learn.cpp",fullname="/home/ying/study/SocialNetwork/ConstPars\
e/SVMKernelCV2/svm_learn.cpp",line="1644"},frame={level="6",addr="0x000000000040ebe5",func="svm_lear\
n_classification",file="svm_learn.cpp",fullname="/home/ying/study/SocialNetwork/ConstParse/SVMKernel\
CV2/svm_learn.cpp",line="835"},frame={level="7",addr="0x0000000000402b69",func="main",file="svm_lear\
n_main.cpp",fullname="/home/ying/study/SocialNetwork/ConstParse/SVMKernelCV2/svm_learn_main.cpp",lin\
e="110"}]

Friday, July 19, 2013

Stanford tool

The tree structure created by Stanford parser has some useful information:

offset: (If not, you need setSpan for the tree.)
Label label = tree.label();
int offset1 = ((HasOffset)label).beginPosition();
int offset2 = ((HasOffset)label).endPosition();


public static int setSpan(Tree t, int left){
        Label label = (Label)t.label();
        if (t.isPreTerminal()) {
            ((HasOffset)label).setBeginPosition(left);
            ((HasOffset)label).setEndPosition(left);
            String labelS = label.value();
            if(labelS.contains("-NONE-") || labelS.contains("-none-")){
                return left;
            }
            return (left + 1);
        }
        int position = left;

        // enumerate through daughter trees
        Tree[] kids = t.children();
        for (Tree kid : kids)
            position =setSpan( kid,position);

        //Parent span
        ((HasOffset)label).setBeginPosition(left);
        ((HasOffset)label).setEndPosition(position - 1);
        return position;
    }


It can get the head word of every node:

String headWord = ((HasWord)(tree.label())).word();

Thursday, July 18, 2013

Using Gaussian kernel for svm-light.

Sometimes it converges very slow. Someone suggests the parameters are not optimized.

So I tuned r in Gaussian kernel. Slow means sensitive to noise, and I need to increase r. More about Gaussian kernel in
http://crsouza.blogspot.ca/2010/03/kernel-functions-for-machine-learning.html


Wednesday, July 17, 2013

Deep Learning.

Start watching the course of neural network. Saw something fun today. He thinks SVM is not a good model for tasks that need structures. And he thinks backpropagation failed in the 90s, because of computer speed and small data.

He said he did not like methods such as retreating to models that allow convex optimization. mmm, isn't this what we learn in Dale's course?

1970-80s, anti-probability, LOL.

Some book I should read: John von Neumann, the computer and the brain. 1958.