如果我按如下方式初始化std :: array,编译器会给出一个关于缺少大括号的警告
std::array<int, 4> a = {1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题:
std::array<int, 4> a = {{1, 2, 3, 4}};
Run Code Online (Sandbox Code Playgroud)
这是警告信息:
missing braces around initializer for 'std::array<int, 4u>::value_type [4] {aka int [4]}' [-Wmissing-braces]
Run Code Online (Sandbox Code Playgroud)
这只是我的gcc版本中的一个错误,还是故意做的?如果是这样,为什么?
由于在运行时可能会调用声明为constexpr的函数,编译器在哪个条件下决定是在编译时还是在运行时计算它?
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
int main(int argc, char** argv)
{
int i = 0;
std::cin >> i;
std::cout << POW(i, 2) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我在编译时是未知的,这可能是编译器将POW()视为在运行时调用的常规函数的原因.然而,这种动态虽然看起来很方便,但却具有一些不切实际的含义.例如,是否有一种情况我希望编译器在编译时计算constexpr函数,编译器决定将其视为普通函数,而它在编译时也会工作?有任何已知的常见陷阱吗?
我刚开始学习Python,发现我可以将一个函数作为另一个函数的参数传递.现在如果我调用foo(bar())
它将不会作为函数指针传递,而是使用函数的返回值.调用foo(bar)
将传递函数,但这样我无法传递任何其他参数.如果我想传递一个调用的函数指针bar(42)
怎么办?
我希望能够重复一个函数,无论我传递给它的是什么参数.
def repeat(function, times):
for calls in range(times):
function()
def foo(s):
print s
repeat(foo("test"), 4)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,该函数foo("test")
应该连续调用4次.有没有办法实现这一点,而不必通过"测试" repeat
代替foo
?
当作为引用返回并作为指针直接传递给另一个函数时,静态变量会发生什么?显然,变量在函数返回后仍然存在,但关于这整个概念的一些事情让我感到烦恼.此时是数据后续的内存,被静态变量占用,被释放了吗?当我不再需要它时,运行时会神奇地注意到它,比如某种垃圾收集吗?
举个例子:
SDL_Rect* XSDL_RectConstr(int x, int y, int w, int h)
{
static SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
return ▭
}
void mainLoop()
{
while(isRunning)
{
pollEvents();
SDL_BlitSurface(someSurface, XSDL_RectConstr(0, 0, 100, 100), screen, NULL);
SDL_Flip(screen);
}
}
Run Code Online (Sandbox Code Playgroud)
rect
SDL_BlitSurface()返回后会发生什么?我看不出它什么时候会被释放.这不是某种内存泄漏吗?
我目前正在开发一个软件项目,该项目需要对象持久性作为其实现的一部分.升级序列化库乍一看似乎完全适合这项工作,但现在我已经尝试使用它,我开始质疑它的整体设计.
库希望用户为用户想要序列化的每个类定义序列化方法.
class Object
{
private:
int member;
public:
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & member;
}
};
Run Code Online (Sandbox Code Playgroud)
如果有问题的类具有属于其他第三方库和API的成员对象,则会出现问题.即使我碰巧使用的那些都在zlib许可下可用,修改库头只是感觉不对.
但是开发人员已经想到了这一点,并提供了一个非侵入式版本,允许在不修改它们的情况下向类添加序列化.辉煌.
template<class Archive>
void serialize(Archive & ar, Object& o, const unsigned int version)
{
ar & o.member;
}
Run Code Online (Sandbox Code Playgroud)
但是,由于该成员是私人成员并且无法从课堂外获得,因此这不太有用.值得庆幸的是,假设的类Object为其封装的成员提供了getter和setter.但是我们现在需要将序列化拆分为单独的保存和加载功能,幸运的是,boost也允许这样做.不幸的是,似乎只有在用户使用侵入式方法时才能进行此拆分.为了告诉提升分裂功能,官方文档引用了这个宏.
BOOST_SERIALIZATION_SPLIT_MEMBER()
Run Code Online (Sandbox Code Playgroud)
这意味着:
template<class Archive>
void serialize(Archive &ar, const unsigned int file_version)
{
boost::serialization::split_member(ar, *this, file_version);
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,这需要放在里面,这正是我想避免在首位的类.
围绕boost邮件列表,我遇到了这个解决方案:
template <class Archive>
void serialize(Archive & ar, Object& o, const unsigned int version) …
Run Code Online (Sandbox Code Playgroud) 几天前,我询问编译器决定是否在编译期间计算constexpr函数.
事实证明,只有在编译时才会评估constexpr,如果所有参数都是常量表达式,并且您指定给它的变量也是常量表达式.
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
template<typename T>
void foobar(T val)
{
std::cout << val << std::endl;
}
int main(int argc, char** argv)
{
foobar(POW((unsigned long long)2, 63));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我被告知是真的,这个代码示例是非常不实际的,因为foobar不接受constexpr(由于某种原因你不能使用consexpr作为参数),POW在运行时被评估,即使它可能是可能的在编译期间计算它.强制编译时评估的明显解决方案是:
auto expr = POW((unsigned long long)2, 63);
foobar(expr);
Run Code Online (Sandbox Code Playgroud)
然而,这迫使我使用额外的代码行,每次我想确保在编译时评估constexpr时都不需要这样做.为了使这更方便一点,我想出了以下可疑的宏:
#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));
Run Code Online (Sandbox Code Playgroud)
尽管它工作得很好,但我觉得好像有些不对劲.创建匿名lambda会影响性能吗?通过rvalue引用返回实际上是将表达式移动到函数参数吗?std :: move如何影响性能?有没有更好的单线解决方案呢?
使用freeglut图书馆玩了一段时间的OpenGL,我决定将GLFW用于我的下一个培训项目,因为我被告知GLUT仅用于学习目的,不应该专业使用.我将lib链接到我的NetBeans项目没有问题,使用mingw32 4.6.2编译得很好.
但是,我在尝试将窗口定位在屏幕中心时遇到了困难.在freeglut下,我以前用过:
glutInitWindowPosition (
(glutGet(GLUT_SCREEN_WIDTH)-RES_X) / 2,
(glutGet(GLUT_SCREEN_HEIGHT)-RES_Y) / 2
);
Run Code Online (Sandbox Code Playgroud)
我找不到任何会返回屏幕大小或宽度的glfw函数.这样的功能根本没有实现吗?
无论我使用哪个C兼容库,当我查看标头定义的常量时,它们总是被定义为十六进制值.例如,在GL/gl.h中:
#define GL_POINTS 0x0000
#define GL_LINES 0x0001
#define GL_LINE_LOOP 0x0002
#define GL_LINE_STRIP 0x0003
#define GL_TRIANGLES 0x0004
#define GL_TRIANGLE_STRIP 0x0005
#define GL_TRIANGLE_FAN 0x0006
#define GL_QUADS 0x0007
#define GL_QUAD_STRIP 0x0008
#define GL_POLYGON 0x0009
Run Code Online (Sandbox Code Playgroud)
这个约定有什么特别的原因,为什么不简单地使用十进制值呢?
将源文件用于基于模板的类(STL和boost)以及将实现放入标头似乎是一种常见的惯例.我假设与头文件和源文件中的声明和实现之间的经典分离相比,这将增加编译包含头文件的源文件所需的时间.这样做的原因可能是因为您必须告诉源文件中的编译器使用哪些模板,这可能会导致文件膨胀.a文件.
假设链接器在库增长时也需要更多时间,那么编译包含库头的源文件所需的时间会更快?
1.不使用.cpp文件并将整个类(包括实现)放入标头中
//foo.hpp
template <class T>
class Foo
{
public:
Foo(){};
T bar()
{
T* t = NULL;
//do stuff
return *t;
}
};
Run Code Online (Sandbox Code Playgroud)
要么
2.在库本身的源文件中显式编译各种类型的模板
//foo.h
template <class T>
class Foo
{
public:
Foo(){};
T bar();
};
//foo.cpp
template <class T>
T Foo<T>::bar()
{
T* t = NULL;
//do stuff
return *t;
}
template class Foo<int>;
template class Foo<float>;
template class Foo<double>;
template class Foo<long long>;
Run Code Online (Sandbox Code Playgroud) c++ templates header compilation-time explicit-instantiation
我一直在观看YouTube上的Qt教程系列,其中作者展示了当按下按钮时如何调用函数.他右键单击Qt Creator IDE中的按钮并选择"Go to slot",从中他选择了可以触发生成函数的信号.由于我习惯使用Netbeans开发,我只是尝试使用嵌入式Qt Designer来跟随他的例子.不幸的是,当我右键单击我的按钮或任何小部件时,没有"转到插槽..."条目.当然,我可以为我的主窗口创建一个新的插槽,然后将按钮的信号连接到它,但是使用单个功能执行它对我来说似乎更方便和干净.有没有办法修复是否,或者如果没有,至少是一种完全通过代码的方式,而不必为每个服务于不同目的的单个按钮添加一个新的插槽到主窗口?谢谢你的帮助.
首先,我是C++编程的初学者.昨天我遇到了一些比较奇怪的事情.我试图通过指向它的指针来确定数组的长度.由于sizeof不起作用,我做了一点谷歌搜索,最后在这个网站上我找到了答案,这是不可能的.相反,我应该在数组的最后一个索引处放置一个超出值的值,并递增计数器,直到达到此索引.因为我不想覆盖最后一个索引中包含的信息,所以我尝试将最后一个索引放在一个索引之后.我预计它会失败,但由于某种原因它没有.
我以为我在其他地方犯了一个错误,那个数组比我指定的更长,所以我做了以下测试:
int a[4];
a[20] = 42;
std::cout << a[20];
Run Code Online (Sandbox Code Playgroud)
输出为42,没有任何错误.为什么这样做?这根本不应该有效,对吧?更有趣的是,这适用于任何基本类型数组.但是,一旦我使用std :: string,程序立即存在1.
有任何想法吗?
我正在寻找一种方法将通用(constexpr,显然)功能传递给模板.它必须能够在不使用lambda的情况下获取任何数量的参数.这是我到目前为止:
template<typename T, T(*FUNC)()> struct CALL
{
static inline constexpr decltype(FUNC()) EXEC()
{
return FUNC();
}
};
Run Code Online (Sandbox Code Playgroud)
但是,只有传递的函数不带参数时才有效.有没有办法让模板接受任何constexpr功能?传递std ::函数似乎不起作用.我想关键是可变参数模板参数,但我不知道在这种情况下如何利用它们.