我要问的是众所周知的"结构的最后一个成员有可变长度"的技巧.它是这样的:
struct T {
int len;
char s[1];
};
struct T *p = malloc(sizeof(struct T) + 100);
p->len = 100;
strcpy(p->s, "hello world");
Run Code Online (Sandbox Code Playgroud)
由于结构在内存中的布局方式,我们可以将结构覆盖在一个大于必要的块上,并将最后一个成员视为大于1 char
指定的大小.
所以问题是:这种技术在技术上是不确定的行为吗?.我希望它是,但很好奇标准对此有何看法.
PS:我知道C99的方法,我希望答案专门针对上面列出的技巧版本.
我有一个相对较旧的应用程序.通过一些小的改动,它几乎完全用Visual C++ 2008构建.我注意到的一件事是我的"调试控制台"工作不正常.基本上在过去,我AllocConsole()
用来为我的调试输出创建一个控制台.然后我会用它freopen
来重定向stdout
到它.这与C和C++风格的IO完美配合.
现在,它似乎只适用于C风格的IO.将内容重定向cout
到分配的控制台的正确方法是什么AllocConsole()
?
这是以前的代码:
if(AllocConsole()) {
freopen("CONOUT$", "wt", stdout);
SetConsoleTitle("Debug Console");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
}
Run Code Online (Sandbox Code Playgroud)
编辑:我发生的一件事是我可以创建一个自定义streambuf,其溢出方法使用C样式IO写入并std::cout
用它替换默认的流缓冲区.但这似乎是一个警察.有没有正确的方法在2008年这样做?或者这可能是MS忽略的东西?
编辑2:好的,所以我已经实现了上面拼写的想法.基本上它看起来像这样:
class outbuf : public std::streambuf {
public:
outbuf() {
setp(0, 0);
}
virtual int_type overflow(int_type c = traits_type::eof()) {
return fputc(c, stdout) == EOF ? traits_type::eof() : c;
}
};
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
// create the console …
Run Code Online (Sandbox Code Playgroud) 我出于好奇而问这个问题.基本上我的问题是当你有一个数据库需要一个行条目来做一些像旗帜一样的东西时,最佳做法是什么?一个很好的例子就是堆栈溢出上的徽章,或者bugzilla中的操作系统字段.可以为给定条目设置标志的任何子集.
通常,我做c和c ++工作,所以我的直觉反应是使用无符号整数字段作为一组可以翻转的位......但我知道这不是一个好的解决方案,原因有几个.其中最明显的是比例能力,我可以拥有多少旗帜的硬上限.
我还可以考虑其他几种解决方案,这些解决方案可以更好地扩展,但会出现性能问题,因为它们需要多次选择才能获得所有信息.
那么,做到这一点的"正确"方法是什么?
我最近在风格上做了一个改变,想看看其他c ++程序员对它的看法以及是否有任何缺点.
本质上,当我需要一个不需要访问给定类成员的实用函数时,我以前做的是这样的:
file.h
class A {
public:
// public interface
private:
static int some_function(int);
};
Run Code Online (Sandbox Code Playgroud)
file.cpp
int A::some_function(int) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
但最近,我更喜欢做更像这样的事情:
file.cpp
namespace {
int some_function(int) {
}
}
// the rest of file.cpp
Run Code Online (Sandbox Code Playgroud)
这是我的思考过程:
最后一个对我来说是最引人注目的.所以我的问题是:这有什么缺点吗?
对于我能想到的大多数目的而言,它们在功能上是等效的.在我看来,private static
函数几乎总是可以在匿名中转换为自由函数namespace
.
编辑:我想到的一件事是,如果给定一个指向要操作的对象的指针,private static
函数就可以访问private
成员,但如果是这样的话,为什么不让它成为非static
成员呢?
你们有什么感想?
boost::shared_ptr
有一个不寻常的构造函数
template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p);
Run Code Online (Sandbox Code Playgroud)
我对这对什么有用感到有些疑惑.基本上它与股份共享r
,但.get()
将返回p
.不 r.get()
!
这意味着您可以执行以下操作:
int main() {
boost::shared_ptr<int> x(new int);
boost::shared_ptr<int> y(x, new int);
std::cout << x.get() << std::endl;
std::cout << y.get() << std::endl;
std::cout << x.use_count() << std::endl;
std::cout << y.use_count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
你会得到这个:
0x8c66008
0x8c66030
2
2
Run Code Online (Sandbox Code Playgroud)
请注意,指针是分开的,但它们都声称具有use_count
2(因为它们共享同一对象的所有权).
因此,所int
拥有的x
将存在只要x
或 即将存在y
.如果我理解文档是正确的,那么第二个int
永远不会被破坏.我通过以下测试程序证实了这一点:
struct T {
T() { std::cout << …
Run Code Online (Sandbox Code Playgroud) 在类定义中初始化静态整型数据成员可以声明const
或constexpr
,但在类定义中初始化非整数的静态数据成员必须是constexpr
:
class MyClass {
static const int w = 5; // okay
static constexpr int x = 5; // okay
static const float y = 1.5; // error!
static constexpr float z = 1.5; // okay
};
Run Code Online (Sandbox Code Playgroud)
有人知道为什么不允许y的声明吗?标准中将其定为非法的部分是9.4.2/3,但为什么它是非法的?
像许多人一样,我对C++ 0x感到非常兴奋.我尝试在新项目中学习和使用新功能,这样我就可以编写最好,最易于维护的代码.
不用说,我喜欢新初始化器背后的想法.所以我在看他们,这些对我有意义:
T x = { 1, 2, 3 }; // like a struct or native array
T x({1, 2, 3}); // copy construct something like an "object literal" in other languages... cool!
return {1, 2, 3}; // similar to above, but returning it, even cooler!
Run Code Online (Sandbox Code Playgroud)
对我来说没有意义的是:
T x{1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
它只是感觉......很奇怪.我不确定人们想要使用哪种语法,这是模仿,它似乎并不"正确".
这种语法背后的设计/思想是什么?
它似乎有所作为的唯一例子是这样的:
std::vector<int> the_vec{4};
Run Code Online (Sandbox Code Playgroud)
它会调用初始化列表构造函数,但为什么不写这个呢:
std::vector<int> the_vec = {4};
Run Code Online (Sandbox Code Playgroud)
并做每个人都已经习惯的事情?
所以这是我一直想知道但却从未确定过的事情.所以这完全是好奇心问题,而不是真正的问题.
据我所知,当你#include <cstdlib>
在std::
命名空间中声明所有事情(当然除了宏)之外.我见过的每个实现都是通过执行以下操作来实现的:
#include <stdlib.h>
namespace std {
using ::abort;
// etc....
}
Run Code Online (Sandbox Code Playgroud)
这当然会影响全局命名空间和std
.这种行为有保证吗?或者实现是否可能将这些内容放入std
全局命名空间中而不是放在全局命名空间中?我能想到的唯一办法做到这一点是有你的libstdc ++实现每一个C函数本身将它们放置在std
直接而不只是包括现有的libc头文件(因为没有机制来移除命名空间的东西).这当然是很多努力,几乎没有任何好处.
我的问题的实质是,以下程序是否严格符合并保证有效?
#include <cstdio>
int main() {
::printf("hello world\n");
}
Run Code Online (Sandbox Code Playgroud)
编辑:我发现的最接近的是这个(17.4.1.2p4):
除了如条款18至27所指出的,每一个报头的CNAME的内容应是相同于相应的头name.h的,如在ISO指定/ IEC 9899:1990编程语言C(第7章),或ISO/IEC :1990编程语言-C修正案1:C完整性,(第7条),酌情包括在内.但是,在C++标准库中,声明和定义(在C中定义为宏的名称除外)都在命名空间std的命名空间范围(3.3.5)内.
说实话,我可以解释任何一种方式."每头CNAME的内容应当相同相应的头name.h的,符合ISO/IEC 9899:1990编程语言C"告诉我,他们可以在全局命名空间是必需的,但"在但是,C++标准库,声明和定义(在C中定义为宏的名称除外)都在命名空间std的命名空间范围(3.3.5)内.说他们在std(但没有指明他们所在的任何其他范围).
对不起,这将是一个很长的帖子,但我觉得你需要所有的代码来看看发生了什么.
所以,我一直在尝试将编译时字符串转换为数据结构解析器.想象一下像正则表达式这样的东西,其中字符串在编译时被"编译"成数据结构但在运行时执行(只要输入字符串当然是常量).但是我遇到了一个我不太明白错误的问题:
基本上,我的设计是一个2遍解析器:
这是事情的样子:
// a class to wrap string constants
class constexpr_string {
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1) {}
public:
constexpr size_t size() const { return size_; }
constexpr size_t capacity() const { return size(); }
constexpr size_t empty() const { return size() != 0; }
public:
constexpr char operator[](size_t n) const { return string_[n]; }
private:
const char *string_;
size_t size_;
};
// would have loved to …
Run Code Online (Sandbox Code Playgroud)