鉴于数组的名称实际上是指向数组的第一个元素的指针,以下代码:
#include <stdio.h>
int main(void)
{
int a[3] = {0, 1, 2};
int *p;
p = a;
printf("%d\n", p[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
1按预期打印.
现在,鉴于我可以创建一个指向指针的指针,我写了以下内容:
#include <stdio.h>
int main(void)
{
int *p0;
int **p1;
int (*p2)[3];
int a[3] = {0, 1, 2};
p0 = a;
p1 = &a;
p2 = &a;
printf("p0[1] = %d\n(*p1)[1] = %d\n(*p2)[1] = %d\n",
p0[1], (*p1)[1], (*p2)[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望它能够编译和打印
p0[1] = 1
(*p1)[1] = 1
(*p2)[1] = 1
Run Code Online (Sandbox Code Playgroud)
但相反,它在编译时出错,说:
test.c: In function ‘main’:
test.c:11:5: …Run Code Online (Sandbox Code Playgroud) 此代码有效:
std::ifstream f(mapFilename.c_str());
std::string s = std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
ParseGameState(s);
Run Code Online (Sandbox Code Playgroud)
因此mapFilename是std::string和void ParseGameState(const std::string&);.
而这不是:
std::ifstream f(mapFilename.c_str());
std::string s(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
ParseGameState(s);
Run Code Online (Sandbox Code Playgroud)
这是错误:
game.cpp: In member function ‘int Game::LoadMapFromFile(const std::string&)’:
game.cpp:423: error: no matching function for call to ‘ParseGameState(std::string (&)(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)()))’
game.cpp:363: note: candidates are: ParseGameState(const std::string&)
Run Code Online (Sandbox Code Playgroud)
所以它似乎s在这种情况下识别为函数声明而不是变量声明.
这是为什么?这是GCC 4.2.1(Apple版本)中的错误吗?或者GCC是否正确处理了这个问题?这在C++标准中是否未定义?
我有一个模板类,我在一个标题中声明了一个方法,并且标题中没有该方法的定义.在.cc文件中,我定义了该方法的特化,而没有在标题中声明它们.在另一个.cc文件中,我为不同的模板参数调用该方法,其中存在特化.它看起来像这样:
foo.h中:
template<typename T>
class Foo {
public:
static int bar();
};
Run Code Online (Sandbox Code Playgroud)
foo.cc:
#include "foo.h"
template<>
int Foo<int>::bar() {
return 1;
}
template<>
int Foo<double>::bar() {
return 2;
}
Run Code Online (Sandbox Code Playgroud)
main.cc:
#include <iostream>
#include "foo.h"
int main(int argc, char **argv) {
std::cout << Foo<int>::bar() << std::endl;
std::cout << Foo<double>::bar() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于所有C++标准(c ++ 98,gnu ++ 98,c ++ 11和gnu ++ 11),该程序与gcc 4.7.2成功编译和链接.输出是:
1
2
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义.因为main.cc转换单元没有看到它的定义bar()或任何特化,所以它期望调用在一些其他转换单元bar()中使用非bar()特定定义的显式实例化.但由于名称修改是可预测的,因此foo.cc中的特殊化具有与非专用定义的显式实例化相同的符号名称,因此main.cc能够使用这些特化而不会在该转换单元中声明它们.
我的问题是:这是一个意外,还是C++标准规定的这种行为?换句话说,这个代码是否可移植?
我能找到的最相关的先前问题是模板类成员专业化的声明,但它不包括这个特定情况.
(如果您想知道为什么这对我来说很重要,那是因为我使用这样的代码作为一种编译时查找表,如果我不声明特化,它会更短.)
我正在回到我的C++研究中,并且真正试图理解基础知识.指针总是给我带来麻烦,我想确保在我继续前行之前真的得到它并且在路上感到困惑.
可悲的是,我一开始就被我正在阅读的教程中的不一致所困扰.有些人以这种方式做指针声明:
int *x
Run Code Online (Sandbox Code Playgroud)
有些人这样做:
int* x
Run Code Online (Sandbox Code Playgroud)
现在两者的前者似乎是迄今为止最常见的.这令人沮丧,因为第二个对我来说更有意义.当我读int*x时,我读到"这是一个int,它的名字是*x",这是不对的.但是当我读到第二个时,我看到"这里是一个int指针,它的名字是x",这是非常准确的.
那么,在我构建自己的心智图之前,两者之间是否存在功能差异?如果我是第二种方式,我会成为麻风病人吗?
谢谢.
我不确定如何在搜索中表达这一点,但是我很好奇是否在eclipse中有一个快捷方式允许我们根据等于之后的内容声明一个变量类型.
例如:
firstname = User.getFirstName();
Run Code Online (Sandbox Code Playgroud)
按下的enter那一刻,它会在行的开头添加"String",使其变为:
String firstname = User.getFirstName();
Run Code Online (Sandbox Code Playgroud)
甚至快捷键也足够了.
有些时候类名可能很长,或类似的东西:Iterator<Entry<String, String>>这足够长,快捷方式或自动添加会很方便.
我不确定这是否存在.
多谢你们.
我喜欢这样一个事实:Go并没有给我百万种方法来做简单的事情 - 借用Python的Zen,"应该有一个 - 最好只有一个 - 显而易见的方法."
但是,我不清楚实例化类型的首选/惯用方法.基本类型很简单:
n := 0
t := 1.5
str := "Hello"
Run Code Online (Sandbox Code Playgroud)
但是结构呢?以下是等效的,如果是,哪个是首选的,为什么?
var f Foo
f := Foo{}
Run Code Online (Sandbox Code Playgroud)
切片怎么样?我可以做var xs []int,xs := []int{}或者xs := make([]int),但我认为第一种选择(与结构相对)与其他选项不同?我认为这也适用于地图.
有了指针,我听说new应该避免.这是一个很好的建议,如果是的话,什么才算是有效的用法new?
我意识到这可能部分是风格问题,但在任何情况下,选择特定风格的理由都会有所帮助.
据我所知,如果源文件需要引用其他文件中的函数,那么它需要包含其头文件,但我不明白为什么源文件包含自己的头文件.头文件中的内容只是作为每个处理时间的函数声明被复制并粘贴到源文件中.对于包含其自己的头文件的源文件,这样的"声明"对我来说似乎没有必要,实际上,项目在从源文件中删除标题后仍然编译并链接没有问题,所以源文件的原因是什么包括它自己的头?
我希望有一个静态函数,我在定义之前在我的.c文件中声明:
//file a.c version 1
static int foo();
...
static int foo()
{
...
}
Run Code Online (Sandbox Code Playgroud)
但是,似乎我可以将static关键字从函数定义中删除,并且我没有得到编译器警告......例如
//file a.c version 2
static int foo();
...
int foo()
{
...
}
Run Code Online (Sandbox Code Playgroud)
假设这两种形式完全相同,我是否正确?
如果是这样,为什么允许这种差异,我应该使用哪种形式?
文章声称
template <class T> class tmp {
public:
int i;
};
auto foo()->auto(*)()->tmp<int>(*)(){
return 0;
}
Run Code Online (Sandbox Code Playgroud)
相当于
template <class T> class tmp{
public:
int i;
};
tmp<int> (*(*foo())())() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不理解第二个代码示例中的复杂函数.我应该在一开始看哪里?我想是的foo.但旁边的统计数据foo将定义foo为指针......基于第一个代码示例,我将把这个片段转换为
tmp<int> (*)() (*)() foo(){ return 0;}
Run Code Online (Sandbox Code Playgroud)
所以foo是一个函数,返回0,但返回类型很棘手:它的返回类型是函数指针,其返回类型又是返回类型为的函数指针tmp<int>.
C23 标准显然引入了使用“auto”关键字进行自动类型推导,请参阅此处,就像 C++11 中一样。然而,似乎存在一些差异。
根据here,https://en.cppreference.com/w/cpp/keyword/auto,在C++11之后,不再auto是C++中的存储持续时间说明符。
然而,我无法轻易找到 C23 的等效声明。在C23中是否仍然auto是C中的存储类说明符?
还可以int auto x = 1;用C23写吗?
编辑:第一个问题的答案是肯定的。但正如 Andrew Henle 在下面的评论中指出的,第二个问题是不同的:
还可以float auto x = 1;用C23写吗?
正如 @AndrewHenle 和 @VladfromMoscow 在标准文档中引用的那样,6.7.1 存储类说明符,第 4 段
auto 仅应出现在具有文件范围的标识符的声明说明符中,或者如果要从初始值设定项推断类型,则应与其他存储类说明符一起出现。
float auto x = 1;如果此声明不在文件范围内,则这似乎不涵盖这种情况。
这句话的解释是什么?
还有一个问题:这句话看起来很混乱,因为我们肯定可以使用 auto 而无需“其他存储说明符”,不是吗?喜欢auto a = 1;。