我正在尝试找到一种方便的方法来初始化'pod'C++结构.现在,考虑以下结构:
struct FooBar {
int foo;
float bar;
};
// just to make all examples work in C and C++:
typedef struct FooBar FooBar;
Run Code Online (Sandbox Code Playgroud)
如果我想在C(!)中方便地初始化它,我可以简单地写:
/* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C
Run Code Online (Sandbox Code Playgroud)
请注意,我想明确地避免使用以下表示法,因为如果我将来更改结构中的任何内容,它会让我感到沮丧:
/* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style?
Run Code Online (Sandbox Code Playgroud)
为了实现与/* A */示例中相同(或至少类似)的C++ ,我将不得不实现一个愚蠢的构造函数:
FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {}
// -> …Run Code Online (Sandbox Code Playgroud) 文档std::numeric_limits<T>说它不应该专门针对非基本类型.数字式用户定义类型怎么样?如果我定义了我自己的T表示数值的类型并重载数字运算符,并且表示的信息numeric_limits是有意义的 - 如果我专门numeric_limits针对该类型,会有什么破坏吗?
C++有几个功能来获取动态存储,其中大部分功能在某些基本方面有所不同.OS通常会添加几个.
由于它们的便携性和相似性,其中两个特别感兴趣:malloc和::operator new.
全局void* operator new(size_t, ::std::nothrow&)和void* malloc(size_t)?之间是否有任何差异(标准和实施)?
由于我所说的似乎有些混乱,请考虑以下两个调用:
void* p = ::std::malloc(10);
void* q = ::operator new(10, ::std::nothrow);
Run Code Online (Sandbox Code Playgroud)
明显和微不足道的区别在于如何释放内存:
::std::free(p);
::operator delete(q);
Run Code Online (Sandbox Code Playgroud)
注意:这个问题不重复,例如new/delete和malloc/free有什么区别?因为它谈到使用实际上不执行任何ctor调用的全局 operator new.
我有一个类层次结构,归结为
class Module { };
struct Port {
Module& owner;
Port(Module& owner) : owner(owner) {}
};
struct InPort : virtual Port { using Port::Port; };
struct OutPort : virtual Port { using Port::Port; };
struct InOutPort : InPort, OutPort { using Port::Port; };
Run Code Online (Sandbox Code Playgroud)
如您所见,我更愿意创建一些基本功能,并以经典的菱形图案继承它.我也想使用构造函数继承使其尽可能地证明未来...
但是,这不起作用如上所述
prog.cpp: In function 'int main()':
prog.cpp:14:15: error: use of deleted function 'InOutPort::InOutPort(Module&)'
InOutPort p(m);
Run Code Online (Sandbox Code Playgroud)
即InOutPort使用更明确的版本替换定义也是不够的:
struct InOutPort : InPort, OutPort { InOutPort(Module& m) : Port(m), InPort(m), OutPort(m) { } }; …Run Code Online (Sandbox Code Playgroud) C++ 11和C++ 14标准(分别是工作草案)在§3.10.1中说:
prvalue("纯"rvalue)是一个不是xvalue的rvalue.[示例:调用返回类型不是引用的函数的结果是prvalue.诸如12,7.3e5或true之类的文字的值也是prvalue. - 末端的例子]
和
rvalue(历史上所谓的,因为rvalues可能出现在赋值表达式的右侧)是xvalue,临时对象(12.2)或其子对象,或者是与对象无关的值.
这引出了一个问题:表达式如何成为"与对象无关的值"?
我的印象是,表达式的目的是返回对象或void(我不希望它也是一个值).
这些表达式有一些简单而常见的例子吗?
编辑1
要进一步复杂化,请考虑以下事项:
int const& x = 3;
int&& y = 4;
Run Code Online (Sandbox Code Playgroud)
在§8.3.2.5的上下文中,其中包含最有趣的片段:
[...]引用应初始化以引用有效的对象或功能[...]
§8.5.3.1强化了这一点:
声明为T&或T &&的变量,即"对类型T的引用"(8.3.2),应由类型为T的对象或函数或可转换为T的对象初始化. [...]
类模板::std::numeric_limits<T>只能为类型实例化,类型T可以是函数的返回值,因为它总是定义成员函数,如static constexpr T min() noexcept { return T(); }(更多信息请参见http://www.cplusplus.com/reference/limits/numeric_limits/) c ++ 03或c ++ 11中的特殊版本.
如果T是,即int[2]实例化将立即导致编译时错误,因为int[2]不能是函数的返回值.
::std::numeric_limits使用安全版本进行包装很容易 - 如果确定实例化::std::numeric_limits是否安全的方法是已知的.这是必要的,因为如果可能的话,应该可以访问有问题的功能.
显而易见(显然是错误的)测试方法::std::numeric_limits<T>::is_specialised不起作用,因为它需要实例化有问题的类模板.
有没有办法测试实例化的安全性,最好不要列举所有已知的坏类型?甚至可能是确定任何类模板实例化是否安全的一般技术?
C11标准ISO/IEC 9899:2011(E)规定了§6.5.16.1/ 1中简单指配的以下约束:
以下其中一项应持有:
- 左操作数具有原子,限定或非限定算术类型,右边有算术类型;
- 左操作数具有与右侧类型兼容的结构或联合类型的原子,限定或非限定版本;
- 左操作数具有原子,限定或非限定指针类型,并且(考虑左值操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的限定或非限定版本的指针,左侧指向的类型具有全部右边指出的那种限定词;
- 左操作数具有原子,限定或非限定指针类型,并且(考虑左值操作数在左值转换后将具有的类型)一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的指针void,左边指向的类型具有右边指向的所有类型的限定符;
- 左操作数是一个原子,限定或非限定指针,右边是一个空指针常量; 要么
- 左操作数的类型为atomic,qualified或nonqualified
_Bool,右边是指针.
我感兴趣的是双方都指向不兼容的不同类型的情况void.如果我理解正确,这应该至少调用UB,因为它违反了这个约束.不兼容类型的一个例子应该是(根据§6.2.7和§6.7.2)int和double.
因此,以下程序应违反:
int main(void) {
int a = 17;
double* p;
p = &a;
(void)p;
}
Run Code Online (Sandbox Code Playgroud)
gcc和clang都警告"-Wincompatible-pointer-types",但不要中止编译(编译-std=c11 -Wall -Wextra -pedantic).
同样,以下程序只会导致"-Wint-conversion"警告,同时编译就好了.
int main(void) {
int a;
double* p;
p = a;
(void)p;
}
Run Code Online (Sandbox Code Playgroud)
来自C++,我预计这些测试用例中的任何一个都需要使用强制转换来编译.是否有任何理由为什么这两个计划都是标准合法的?或者,是否至少有重要的历史原因支持这种代码风格,即使通过明确使用-std=c11而不是禁用有趣的GNU C扩展-std=gnu11?
这个问题是关于采用静态已知大小的数组的函数.
以下面的最小程序为例:
#include <iostream>
template<size_t N>
void arrfun_a(int a[N])
{
for(size_t i = 0; i < N; ++i)
std::cout << a[i]++ << " ";
}
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
arrfun_a<5>(a);
std::cout << std::endl;
arrfun_a<5>(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行时,打印预期结果:
2 3 4 5 6
3 4 5 6 7
Run Code Online (Sandbox Code Playgroud)
但是,当我试图让我的编译器(VS 2010)推断出5它时could not deduce template argument for 'int [n]' from 'int [5]'.
一些研究导致arrfun_b模板参数推导工作的更新:
template<size_t n>
void arrfun_b(int …Run Code Online (Sandbox Code Playgroud) 你可以两次继承同一个班吗?例如:
class Base {
};
class Foo : public Base {
};
class Bar : public Base {
};
class Baz : public Foo, public Bar {
//is this legal?
// are there restrictions on Base
// (e.g. only virtual methods or a virtual base)?
};
Run Code Online (Sandbox Code Playgroud) 让我们考虑以下两个代码
第一:
for (int i=0;i<10000000;i++)
{
char* tab = new char[500];
delete[] tab;
}
Run Code Online (Sandbox Code Playgroud)
第二:
for (int i=0;i<10000000;i++)
{
char tab[500];
}
Run Code Online (Sandbox Code Playgroud)
峰值内存使用率几乎相同,但第二个代码运行速度比第一个快20倍.
问题
是因为第一个代码数组存储在堆上,而第二个数组存储在堆栈中?