小编Jim*_*mmy的帖子

为什么函数指针定义适用于任意数量的&符号'&'或星号'*'?

为什么以下工作?

void foo() {
    cout << "Foo to you too!\n";
};

int main() {
    void (*p1_foo)() = foo;
    void (*p2_foo)() = *foo;
    void (*p3_foo)() = &foo;
    void (*p4_foo)() = *&foo;
    void (*p5_foo)() = &*foo;
    void (*p6_foo)() = **foo;
    void (*p7_foo)() = **********************foo;

    (*p1_foo)();
    (*p2_foo)();
    (*p3_foo)();
    (*p4_foo)();
    (*p5_foo)();
    (*p6_foo)();
    (*p7_foo)();
}
Run Code Online (Sandbox Code Playgroud)

c c++ function-pointers

204
推荐指数
2
解决办法
1万
查看次数

根据定义,不将"虚拟析构函数"置于接口中,使其不再是接口吗?

所以这是我所在的框.我想了解为什么在你的接口类中有一个"虚拟析构函数"很重要.如果你可以挂到最后,你会看到为什么那些东西在引号中...我也想让所有的词汇绝对正确.到目前为止,这是我处理过程的地方:

  1. 有时您有基类,有时您有从基类继承的派生类.

  2. 如果你有一个基指针,它发现自己指向一个派生对象,你还希望从该指针指向一个派生对象的成员函数调用,就像它实际上被调用一样从派生对象中,您调用的成员函数最好在基类中声明为virtual.

  3. 接口是任何只有纯虚函数的类.如果从此接口类派生新类并实现所有纯虚函数,则最终可以创建派生类的实例.

  4. 你永远不可能有一个接口类的实例,但你可以有一个指向接口类的实例.

  5. 如果你有一个实际指向派生类对象的指针接口类(实际上,我想如果#4是正确的话,它总是必须这样),如果你决定通过它删除那个对象你的指针,如果你的接口类中没有"虚拟析构函数",你破坏派生对象的意图只会作为一个调用来执行,以破坏基础对象(即接口类),因为没有虚拟析构函数,事物永远不会达到实际调用派生对象的析构函数的程度 - 从而导致内存泄漏.

唷.好的,如果这听起来是正确的,请回答我的问题.仅仅在你的界面中声明一个虚拟析构函数就足够了:

virtual ~iFace();
Run Code Online (Sandbox Code Playgroud)

这对我来说是错误的......所以如果你像这样使析构函数变为虚拟,会发生什么:

virtual ~iFace() = 0;
Run Code Online (Sandbox Code Playgroud)

既然它们只是声明,那么它们中的任何一个都算是"接口类中的虚拟析构函数"吗?你甚至可以有一个声明但未定义的析构函数吗?只有它是纯粹的虚拟我猜...

无论如何,所以回到标题问题......我真的要尽可能快......这是拍摄的钱......如果你的"界面类中的虚拟析构函数"需要至少一个像这样的空定义:

virtual ~iFace() {};
Run Code Online (Sandbox Code Playgroud)

那个成员函数不是纯虚拟的(不能因为你给了它一个定义),因此你的类不再是一个接口(它不仅包含纯虚拟成员函数).

这意味着如果为接口定义虚拟析构函数,则不再具有接口(而只是一些抽象基类).这只是滥用语言吗?我明白发生了什么吗?

注意:这一切都来自于问自己"什么是界面?" 然后阅读这个问题的答案: 你如何在C++中声明一个接口?

希望漫长的骑行时间不会太长,但我决心完全理解这些概念及其相关的词汇.

c++ terminology interface pure-virtual

26
推荐指数
3
解决办法
1万
查看次数

对于嵌套模板,何时`>>`成为标准C++(而不是`>>``)?

我似乎记得,在过去的时候,>在处理嵌套模板参数时,要警告不要将两个字符紧挨着(没有空格).我甚至模糊地记得声明向量的向量,并遇到这个编译错误.

但现在我发现编译可怕的东西绝对没有错>>...

我的问题是这样的:

该公约在什么时候成为可接受的做法?

它是标准C++的一部分吗?

它是否始终是标准的一部分,我在大学里使用的编译器(以及我所拥有的教授)只是不支持它?

也许这些问题有点历史,但对我而言,正确的历史背景似乎使得实际的记忆变得微不足道.

c++ templates

26
推荐指数
1
解决办法
4114
查看次数

为什么不删除我的指针删除我的指针?

因此,为了更好地理解新/删除(真的用小例子向我自己证明为什么接口需要虚拟析构函数),我想了解内存泄漏,以便我可能生活在对它们的恐惧中.但是我很难接触到泄漏,可以这么说; 实际上,我也很难用new/delete.

这是我最简单的版本:

int* P1 = new int(43);

cout<<"P1 = "<<P1<<endl;
cout<<"*P1 = "<<*P1<<endl;

delete P1;

cout<<"P1 = "<<P1<<endl;
cout<<"*P1 = "<<*P1<<endl;
Run Code Online (Sandbox Code Playgroud)

这打印:

P1 = 0xcc0340
*P1 = 43
P1 = 0xcc0340
*P1 = 43
Run Code Online (Sandbox Code Playgroud)

我在课堂上有一些更复杂的东西,但是这个例子说明了我的失败.我认为删除需要一个指针并释放它的内存,从而使指针无效或至少它指向什么?我必须做一些非常简单的事情.

c++ memory-leaks undefined-behavior

15
推荐指数
3
解决办法
1128
查看次数

在声明对Ints数组的引用时,为什么它必须是对const指针的引用?

注意:我正在使用g ++编译器(我听说这是非常好的,并且应该非常接近标准).


假设您已经声明了一组int:

int a[3] = { 4, 5, 6 };
Run Code Online (Sandbox Code Playgroud)

现在让我们说你真的想要声明对该数组的引用(除了Bjarne说语言支持它之外,没关系为什么).

案例1 - 如果您尝试:

int*& ra = a;
Run Code Online (Sandbox Code Playgroud)

那么编译器就会说:

"invalid initialization of non-const reference of type `int*&' from a temporary of type `int*'"  
Run Code Online (Sandbox Code Playgroud)

首先,为什么'a'是一个临时变量(即它在内存中没有位置?)......

无论如何,没问题,每当我看到一个非常量错误时,我会尝试抛出一个const ...

案例2 - 如果您尝试:

int*const&rca = a;  //wish I knew where the spaces should go (but my other post asking about this sort of protocol got a negative rank while many of the answers got ranked highly -- aha! there are stupid questions!) 
Run Code Online (Sandbox Code Playgroud)

然后一切都很酷,它编译,你得到一个数组的引用. …

c++ arrays pointers const reference

14
推荐指数
2
解决办法
2万
查看次数

一旦T数组衰减成指向T的指针,它是否可以再次成为T数组?

那么让我们说我有一个数组:

int a[3] = { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)

现在,如果我要检查'a'的类型,我会得到:

cout<<typeid(a).name(); // prints 'A3_i'
Run Code Online (Sandbox Code Playgroud)

现在如果我取'a'的地址,然后取消引用该地址,类型不会改变(我真的很喜欢,因为在我看来'取地址'和'取消引用'是反向操作):

cout<<typeid(*&a).name(); // also prints 'A3_i'
Run Code Online (Sandbox Code Playgroud)

然而,如果我首先取消引用'a',然后取用它的地址,类型确实会改变(我承认我很难不喜欢,因为当我取消引用数组时我应该得到一个int,当我拿到地址时那个int,我应该得到一个指向int的指针,事实证明我做了):

cout<<typeid(&*a).name(); // prints 'Pi'
Run Code Online (Sandbox Code Playgroud)

所以这是我的两个问题:

1)一旦数组类型已经衰减成指针类型,无论如何都要将它恢复为数组类型?

我尝试了一种明显的铸造策略 - 就像你不关心一样:

cout<<typeid( (int[3]) &*a).name(); // does not compile
// "error: ISO C++ forbids casting to an array type `int [3]'"
Run Code Online (Sandbox Code Playgroud)

还有另一个演员可以奏效吗?或者这种类型的转换严格禁止?

2)你是否能够回到数组类型,究竟是什么信息在衰变到指针过程中被切片和丢失?

我知道指针类型和数组类型不等价.我假设array-type是存储在指针类型中的信息的严格超集.这听起来不错吗?

我在其他问题中已经读过,数组类型中的额外信息是:知道数组是否在堆栈上,以及它的大小(它必须以某种方式知道数组的大小,因为它是类型,对吗?).数组类型中是否隐藏了其他任何信息?

c++ arrays pointers

14
推荐指数
1
解决办法
702
查看次数

为什么我的unordered_map自行排序?

所以我正在玩unordered_mapSTL 的新标准化.我的代码有点像这样,我只是创建一个unordered_map,填充并打印出来:

    unordered_map<int,string> m1;

    m1[5]="lamb";
    m1[2]="had";
    m1[3]="a";
    m1[1]="mary";
    m1[4]="little";
    m1[7]="fleece";
    m1[6]="whose";
    m1[10]="fleecey";
    m1[8]="was";
    m1[9]="all";

for(unordered_map<int,string>::const_iterator i = m1.begin(); i != m1.end(); ++i)
cout<<i->first<<" "<<i->second<<endl;
Run Code Online (Sandbox Code Playgroud)

但是,我获得的输出因此被订购:

1 mary
2 had
3 a
4 little
5 lamb
6 whose
7 fleece
8 was
9 all
10 fleecey
Run Code Online (Sandbox Code Playgroud)

但是我不想为我的地图订购付出代价!这就是我使用unordered_map的原因......这里发生了什么?

附加说明:我正在使用gcc version 4.3.4 20090804 (release) 1 (GCC)并正在编译这样的g++ -std=c++0X maptest.cpp

unordered-map map c++11

8
推荐指数
1
解决办法
1749
查看次数

如何在MATLAB中绘制水平直方图?

我看了,找不到这个问题的答案,所以这里就是这样.

我有一些数据(1 X 1000矢量称为数据),我想绘制直方图信息.如果我使用该histogram(data)命令,那么我得到一个足够好的直方图,其中x轴被均匀地划分为十个桶(数据的最大值和最小值之间的十个相等间隔的中点值),并且y轴记录如何每个桶都发生了很多事情.

我真正想要的是相同的情节,只是y轴代表铲斗间隔,x轴代表每个铲斗的数量......

这样我就可以将它粘贴到一些其他信息旁边的子图中,一切都会更容易理解(看起来非常酷).有什么简单的方法可以实现这一目标?谢谢!

matlab plot histogram

8
推荐指数
2
解决办法
2万
查看次数

是否未明确指定未初始化的数据行为?

注意:我正在使用g ++编译器(我听说这是非常好的,并且应该非常接近标准).


我有一个我能想到的最简单的课程:

class BaseClass  {
  public:
    int pub;
};
Run Code Online (Sandbox Code Playgroud)

然后我有三个同样简单的程序来创建BaseClass对象并打印出他们数据的[未初始化]值.


情况1

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 1629556548
Run Code Online (Sandbox Code Playgroud)

哪个好.我实际上认为它会被初始化为零,因为它是POD或Plain Old Datatype或类似的东西,但我想不是吗?到现在为止还挺好.


案例2

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 1629556548
B2.pub = 0
Run Code Online (Sandbox Code Playgroud)

这绝对是奇怪的.我以相同的方式创建了两个相同的对象.一个被初始化而另一个没有.


案例3

BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
BaseClass* pB3 = new BaseClass;
cout<<"B3.pub = "<<pB3->pub<<endl;
Run Code Online (Sandbox Code Playgroud)

打印出:

B1.pub = 0
B2.pub = 0
B3.pub = 0
Run Code Online (Sandbox Code Playgroud)

这是最奇怪的.它们都被初始化为零.我所做的只是添加两行代码,它改变了以前的行为.


那么这只是"未初始化的数据导致未指明的行为"的情况,还是"引擎盖下"更合乎逻辑?

我真的想了解默认的构造函数/析构函数行为,因为我觉得完全理解继承的东西非常重要.

c++ initialization

6
推荐指数
1
解决办法
1133
查看次数

这个解释对于无法编译的C代码是否准确?

涉嫌采访的问答在这里.

以下代码是否会编译(在C中)?

#define X 8;
int main(void)
{
    ++X; // will this line compile?
}`
Run Code Online (Sandbox Code Playgroud)

我不是C的专家,但我知道一些C++并认为:当然不是,你不能增加数字8,它是一个右值.当然,预处理程序替换X8尝试编译之前,并且当它尝试编译,它就会失败正是由于这个原因.然后,我是一个阅读面试问题的网站,所以我想谁知道...

这是给出的解释:

"严格来说,前缀(或后缀)增量运算符的操作数必须是一个不可修改的左值.现在我们知道左值是什么,我们必须问自己X是否是左值.X是一个宏,这意味着它不能识别内存中的位置 - 宏通过预处理器使用简单的文本替换.因为宏不存在于内存区域,所以它们不是左值.这意味着X不能用作前缀增量的操作数因此,上面显示的代码将无法编译."

这个解释是否像我认为的那样是无聊的?

你上面能找到多少错误?我想也许这应该是面试问题......

这很有趣:

"直观地说,你可能会说上面的代码无法编译 - 如果不确切知道原因.但是,在面试的情况下,你会被期望提供一些像上面给出的那样的推理.简单的是或否答案刚赢了"在接受采访时削减它." (!)

c

6
推荐指数
2
解决办法
339
查看次数