虚拟函数如何在与位置无关的代码中实现?
我知道如果我的类有虚函数,编译器通常会为它生成一个包含所有虚函数地址的vtable,并在我的类的每个对象中存储一个指向vtable的指针.
现在,如果我的代码与位置无关,则编译器无法知道虚函数的地址(或任何函数).那它是做什么的?
我想知道真正的编译器是做什么的(不是理论上可行的); 我最感兴趣的是Linux 32位平台,但其他平台也有点有趣.
您好我是这个网站的新手,我需要一些帮助来理解在C中编码需要字符串的结构时会被视为"规范"的内容.基本上我想知道在使用C中的结构来跟踪结构所需的所有内存时,下列哪种方式将被视为"行业标准":
1)固定尺寸字符串:
typedef struct
{
int damage;
char name[40];
} Item;
Run Code Online (Sandbox Code Playgroud)
我现在可以使用 sizeof(Item)
2)字符数组指针
typedef struct
{
int damage;
char *name;
} Item;
Run Code Online (Sandbox Code Playgroud)
我知道我可以存储name使用第二个变量的大小,但还有另一种方法吗?
i)使用固定尺寸是否有任何其他优势(1)
char name[40];
Run Code Online (Sandbox Code Playgroud)
与执行以下操作并使用指向char数组的指针(2)?
char *name;
Run Code Online (Sandbox Code Playgroud)
如果是的话,有什么好处?
ii)此外,字符串是否使用指向char数组(2)的指针将按顺序存储在结构之后(紧接在指向字符串的指针之后),还是存储在内存中的其他位置?
iii)我想知道如何找到char *字符串变量的长度(不使用a size_t或整数值来存储长度)
我的大型应用程序有这种结构:
int main()
{
try {
...
} catch (std::exception& e) {
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
在调用堆栈内部,各种对象检查其内部状态,std::runtime_exception如果它们检测到不好的东西则抛出.全包异常处理程序捕获它,打印一些中等有用的信息并终止程序.
但是,当我在MS Visual Studio下调试时,我可以从没有任何异常处理程序中受益:Visual Studio有自己的,非常有用的处理程序,它会在抛出异常的地方停止我的应用程序,所以我可以检查一下出错.
如何有条件地捕获我的异常?
我尝试了以下方法:
try {
...
} catch (std::exception& e) {
if (IsDebuggerPresent())
throw;
else
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这给出了一个奇怪的结果:Visual Studio捕获了重新抛出的异常,并向我展示了抛出异常的位置的堆栈跟踪.但是,我的应用程序中的所有对象显然都被破坏了,我看不到例如局部变量或成员变量.
我可以使异常处理程序以编译标志为条件:
#ifdef NDEBUG
try {
#endif
...
#ifdef NDEBUG
} catch (std::exception& e) { …Run Code Online (Sandbox Code Playgroud) 虽然以下两个编译(使用Visual Studio 2013),其中一个更加"正确"的C++习语?在调用基类构造函数和声明成员时,我特别谈到显式模板参数.标准是否对此有看法?有一个很好的实际理由偏爱一个而不是另一个吗?
template<class T>
class Bar1 : public Base<T>
{
public:
Bar1() : Base() {}
Bar1(T value) : Base(value) {}
Bar1(Bar1 const & other) : Base(other.value) {}
void Foo(Bar1 const & other)
{
// Some foo related activity.
}
};
template<class T>
class Bar2 : public Base<T>
{
public:
Bar2() : Base<T>() {}
Bar2(T value) : Base<T>(value) {}
Bar2(Bar2<T> const & other) : Base<T>(other.value) {}
void Foo(Bar2<T> const & other)
{
// Some foo related activity.
}
};
Run Code Online (Sandbox Code Playgroud) 我读过,当我知道 Y 和 X 时,最好通过计算atan2(y,x)来获取角度,而不是使用带有 asin 和 acos 的单个值。我试图深入研究math.hlib 但没有找到任何公式。
有人可以解释为什么atan2更好吗?
我有一个只有静态成员的类.
我想在退出时使用"atexit"库函数注册其成员函数之一(下面的代码中的VerifyClean).
在C++常见问题解答说,我必须指定为extern"C"为我要注册这样,就像在下面的例子中的功能.
class Example
{
public:
static void Initialize();
static void DoDirtyStuff {++dirtLevel;}
static void CleanUpStuff {--dirtLevel;}
private:
static void VerifyClean();
// DOESN'T COMPILE: extern "C" static void VerifyClean();
static int dirtLevel;
}
int Example::dirtLevel;
extern "C" void Example::VerifyClean() // DO I NEED extern "C" HERE?
{
assert(dirtLevel == 0);
}
void Example::Initialize()
{
dirtLevel = 0;
atexit(&VerifyClean);
}
Run Code Online (Sandbox Code Playgroud)
我真的必须使用extern"C"吗?
如果我将"atexit"替换为非库函数(在纯C中实现),答案是否会改变?
如果函数VerifyClean是公共的,我决定直接从C++代码调用它,我会得到链接错误或运行时崩溃吗?我问这个是因为声明根本没有提到extern"C",所以常规的C++代码可能会错误地处理函数调用.这在我的MS Visual Studio 2005系统上运行正常.
我经常使用"较长"类型变量赋值为"较短"变量,例如intto short或uint32_tto uint8_t.有一天,我决定使用gcc在我的代码中找到所有这些情况,但令我惊讶的是gcc没有输出任何警告!
int long_value;
short short_value;
std::cin >> long_value; // Example input: 32769
short_value = long_value; // MS Visual Studio complains here at warning level 4
std::cout << "Long: " << long_value << '\n'; // My example output: 32769
std::cout << "Short: " << short_value << '\n'; // My example output: -32767
Run Code Online (Sandbox Code Playgroud)
使用gcc -Wall或gcc -Wconversion没有帮助(gcc没有输出任何警告).实际上,它从不输出任何输入和输出类型的警告(例如long和unsigned char).
我从未在gcc中发现过一个真正的错误,所以我几乎可以肯定这种行为是有道理的.
那么为什么没有警告?
更新:我使用gcc 4.1.2.
我目前正在使用popen由两个编译器编译的代码中的函数:MS Visual Studio和gcc(在linux上).我可能想稍后添加gcc(在MinGW上).
该函数被调用popen为gcc,但_popen对于MSVS,所以我在源代码中添加了以下内容:
#ifdef _MSC_VER
#define popen _popen
#define pclose _pclose
#endif
Run Code Online (Sandbox Code Playgroud)
这是有效的,但我想了解是否存在针对此类问题的标准解决方案(我记得与stricmp/ 的类似情况strcasecmp).具体来说,我想了解以下内容:
_MSC_VER正确的旗帜依赖吗?我选择它是因为我觉得linux环境"更标准".#define放在一些头文件中,那么#include它是在之前还是之后stdio.h(对于这种情况popen)是否重要?_popen被定义为宏本身,我有可能#define失败吗?我应该使用"新"代币my_popen,因为这个或那个原因?我正在使用MS Visual Studio中的SSE2指令集.我用它来做16位数据的计算.
假设我有8个值加载到SSE寄存器中.我想为42所有这些添加常量(例如).这是我希望我的代码看起来如何.
__m128i values; // 8 values, 16 bits each
const __m128i my_const_42 = ???; // What should i write here?
values = _mm_add_epi16(values, my_const_2); // Add 42 to the 8 values
Run Code Online (Sandbox Code Playgroud)
现在,我该如何定义常数?以下两种方式有效,但一种方法效率低下,另一方面很难看.
my_const_42 = _mm_set_epi16(42, 42, 42, 42, 42, 42, 42, 42) - 编译器生成8个命令来"构建"常量my_const_42 = {42, 0, 42, 0, 42, 0, 42, 0, 42, 0, 42, 0, 42, 0, 42, 0} - 很难理解发生了什么; 改变42到如-42不是小事有没有办法更方便地表达128位常数?
有谁知道对数组进行 k 近似排序的算法吗?
我们被要求找到 k 近似排序的算法,它应该在 O(n log(n/k)) 中运行。但我似乎找不到任何。
K-大约。排序意味着数组和任何 1 <= i <= nk 使得 sum a[j] <= sum a[j] i<=j<= i+k-1 i+1<=j<= i+k
c++ ×5
c ×3
arrays ×2
gcc ×2
algorithm ×1
debugging ×1
exception ×1
intrinsics ×1
optimization ×1
performance ×1
pointers ×1
popen ×1
portability ×1
sorting ×1
sse ×1
string ×1
syntax ×1
templates ×1
trigonometry ×1
vtable ×1