下面的代码安全吗?编写类似于此的代码可能很诱人:
#include <map>
const std::map<const char*, int> m = {
{"text1", 1},
{"text2", 2}
};
int main () {
volatile const auto a = m.at("text1");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该映射仅用于字符串文字.
我认为它是完全合法的并且似乎正在工作,但是我从未看到保证在两个不同的地方使用的文字指针是相同的.我无法让编译器为具有相同内容的文字生成两个单独的指针,所以我开始怀疑这个假设是多么坚定.
我只对具有相同内容的文字是否可以有不同的指针感兴趣.或者更正式的,上面的代码可以除外吗?
我知道有一种编写代码的方法可以确保它有效,我认为上面的方法很危险,因为编译器可以决定为文字分配两个不同的存储,特别是如果它们放在不同的翻译单元中.我对吗?
问题是我们是否引入了使优化程序跳闸的未定义行为,还是可以针对gcc提交错误报告?
很抱歉缺少更好的标题,但是它非常脆弱,我们几乎可以肯定这是一个错误。最小的示例不是我们最喜欢的设计,而是基于崩溃的生产代码:
#include <iostream>
struct Node
{
Node(Node* parent) {
if(parent) {
parent->child_ = this;
}
}
Node* child()
{
return child_;
}
Node* child_ = nullptr;
};
void walk(Node* module, int cleanup) {
if(module != nullptr) {
if(!cleanup) {
std::cerr << "No cleanup";
}
walk(module->child(), cleanup);
if(cleanup) {
delete module;
}
}
}
int main (){
Node* top = new Node(nullptr);
Node* child = new Node(top);
walk(top,1);
}
Run Code Online (Sandbox Code Playgroud)
与编译-O1 -foptimize-sibling-calls -ftree-vrp
。Godbolt示例:https://gcc.godbolt.org/z/4VijKb
module->child()
模块为时,程序崩溃调用0x0
。在检查汇编程序时,我们注意到 …
我有一个玩具示例,我想在架构上进行修改以删除Processor
on的类型依赖性EmitterT
:
#include <iostream>
#include <utility>
using namespace std;
struct Emitter {
void e(int) { cout << "emitting int\n";}
void e(double) { cout << "emitting double\n";}
void e(char*) { cout << "emitting char*\n";}
void e(const char*) { cout << "emitting const char*\n";}
};
template <typename EmitterT>
struct Processor {
Processor(EmitterT e) : e_{e} {}
template <typename T>
void process(T&& value) {
cout << "some processing... ";
e_(std::forward<T>(value));
}
EmitterT e_;
};
template<typename Emitter_>
Processor<Emitter_> makeProcessor(Emitter_ e) { …
Run Code Online (Sandbox Code Playgroud) 我的问题很简单,我很惊讶我找不到任何相关的东西.可能它很容易或完全愚蠢(或者我无法搜索).
正如标题所说,是否可以std::vector
在已经分配的内存上使用,因此它不会从start开始分配新元素,而是使用给定的内容.我会想象它像:
T1 *buffer = new T1[some_size];
std::vector<T2> v(buffer, some_size); // <- ofc doesn't work
Run Code Online (Sandbox Code Playgroud)
相反的是非常简单的(可能不漂亮但是)有效:
std::vector<T2> v(some_size);
T1 *buffer = &v[0];
Run Code Online (Sandbox Code Playgroud)
存储保证是连续的,因此它与迭代器一样安全.
我的动机很简单.我传递一些原始内存数据,即字节,因为我知道他们在其他地方的解释我想将它们转换回有意义的东西.我可以做一个reinterpret_cast
并使用普通的c风格数组,但我更喜欢c ++设施.
我觉得这应该是安全的buffer
,因为我们放弃了向量的所有权,因为它需要能够重新分配.
我有以下工作代码:
#include <string>
#include <iostream>
class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};
int main(void){
A a;
std::cout << a.test << '\n';
}
Run Code Online (Sandbox Code Playgroud)
是否有充分理由不能进行测试static const
?我确实在c ++ 11之前理解它受到标准的限制.我认为c ++ 11引入了类内初始化,使其更友好一些.很长一段时间以来,我也没有这种语义可用于整数类型.
当然它适用于以类的形式进行的类外初始化 const std::string A::test = "42";
我想,如果你能把它变成非静态的,那么问题在于其中一个.初始化它的类外范围(通常const
是在对象实例化期间创建的).但是,如果您创建一个独立于该类的任何其他成员的对象,我认为这不是问题.第二个是静态成员的多个定义.例如,如果它包含在几个中.cpp
文件,登陆到几个目标文件,然后链接器将这些对象链接在一起(例如,一个可执行文件)会有麻烦,因为它们将包含相同符号的副本.据我所知,这完全等同于在标题中的类声明下提供类外权利的情况,然后在多个地方包含这个公共标题.我记得,这会导致链接器错误.
但是,现在处理此问题的责任转移到用户/程序员.如果想要拥有一个static
需要提供类外定义的库,则将其编译为单独的目标文件,然后将所有其他对象链接到此文件,因此只有一个二进制定义的副本符号.
我阅读了答案中我们是否还需要单独定义静态成员,即使它们是在类定义中初始化的?而我为什么不能初始化非const静态成员或类的静态数组?.
我还是想知道:
constexpr
与用户定义的文字机制一起使用.clang和g ++都说变量不能有非文字类型.也许我可以做一个.(也许出于某种原因,这也是一个坏主意)static const
应该是二进制精确的不可变副本.如果我遗失或错误理解某事,也请评论.
我的问题基本上已在标题中完整陈述,但让我详细说明.
问题:
也许值得重新说明,virtual
方法必须多么复杂/简单,使机制成为一个相当大的开销?这有什么经验法则吗?例如,如果需要10分钟,使用I/O,复杂if
语句,内存操作等,这不是问题.或者,如果您virtual get_r() { return sqrt( x*x + y*y); };
在循环中编写并调用它,您将遇到麻烦.
我希望这个问题不是太笼统,因为我寻求一些一般但具体的技术答案.无论是难以分辨还是不可能,或者虚拟调用需要花费如此多的时间/周期资源,而数学需要这样,I/O就是这样.
也许一些技术人员知道要比较的一般数字或进行一些分析,并且可以分享一般性结论.令人难以置信的是,我不知道如何进行那些花哨的asm
分析= /.
我还想提出一些理由,以及我的用例.
我认为我看到的问题不仅仅是人们在干旱期间为了表现而不在森林中使用像开放式火灾这样的虚拟现象,而是为了表现,并且很多人都问他们"你是否绝对确定虚拟开销在你的案例中确实是一个问题?".
在我最近的工作中,我遇到了一个可以放在河两岸的问题,我相信.
另外请记住我不问如何改进界面的实现.我相信我知道该怎么做.我问是否有可能告诉他们什么时候做,或者选择哪种权利.
用例:
我运行了一些模拟.我有一个基本上提供运行环境的类.有一个基类,以及一个定义一些不同工作流的派生类.Base将东西收集为通用逻辑并分配I/O源和接收器.衍生品通过实施或多或少地定义特定的工作流程RunEnv::run()
.我认为这是一个有效的设计.现在让我们假设作为工作流主体的对象可以放在2D或3D平面中.工作流程在两种情况下都是通用/可互换的,因此我们正在处理的对象可以具有通用接口,尽管对于非常简单的方法Object::get_r()
.最重要的是,我们可以为环境定义一些stat logger.
最初我想提供一些代码片段,但最终有5个类和2-4个方法,每个都是墙code
.我可以根据要求发布它,但它会将问题延长到当前大小的两倍.
关键点是:RunEnv::run()
是主循环.通常很长(5分钟-5小时).它提供基本的时间检测,呼叫RunEnv::process_iteration()
和RunEnv::log_stats()
.一切都是虚拟的.理由是.我可以推导出RunEnv
,run()
例如针对不同的停止条件重新设计.我可以重新设计process_iteration()
,例如使用多线程,如果我必须处理一个对象池,以各种方式处理它们.此外,不同的工作流程还需要记录不同的统计信息.RunEnv::log_stats()
只是一个将已计算的有趣统计数据输出到a中的调用std::ostream
.我想使用虚拟机并没有真正的影响.
现在让我们假设迭代通过计算对象到原点的距离来工作.所以我们有接口double Obj::get_r();
.Obj
是2D和3D案例的实现.在两种情况下,getter都是一个简单的数学运算,有2-3次乘法和加法.
我还尝试了不同的内存处理.例如,有时坐标数据存储在私有变量中,有时存储在共享池中,因此即使get_x()
可以通过实现get_x(){return x;};
或虚拟来实现get_x(){ return pool[my_num*dim+x_offset]; };
.想象一下计算一些东西get_r(){ sqrt(get_x()*get_x() + get_y()*get_y()) ;};
.我怀疑这里的虚拟会破坏性能.
问题似乎很简单.虽然文档说它确实:
public sealed class KeyCollection : ICollection<TKey>,
IReadOnlyCollection<TKey>, IEnumerable<TKey>, ICollection, IEnumerable
Run Code Online (Sandbox Code Playgroud)
以下代码给出了错误:
class MyKeys<T>
{
readonly Dictionary<T, T> dict = new Dictionary<T, T> ();
public IReadOnlyCollection<T> Keys { get { return dict.Keys; } set; }
}
Run Code Online (Sandbox Code Playgroud)
说没有转换KeyCollection<T>
为IReadOnlyCollection<T>
.
此外,波兰语文档(法语也就此而言)说它没有:
[SerializableAttribute]
public sealed class KeyCollection : ICollection<TKey>,
IEnumerable<TKey>, ICollection, IEnumerable
Run Code Online (Sandbox Code Playgroud)
这是什么?
如果是英文文档中的错误,还有一个奖励问题:
有没有办法获得Keys
只读集合?
我想在没有不必要的移动或复制的情况下取出临时成员.
假设我有:
class TP {
T _t1, _t2;
};
Run Code Online (Sandbox Code Playgroud)
我想得到_t1
,_t2
来自TP()
.没有复制/移动成员是否可能?
我尝试过使用元组并试图"转发"(我认为不可能)成员,但我能得到的最好的是一个动作,或者成员立即死亡.
在下面的操场中使用B::as_tuple2
最终会员过早死亡,除非结果绑定到非ref类型,否则会移动成员.在客户端,B::as_tuple
简单的移动是安全的auto
.
我认为这应该在技术上是可行的,因为临时死亡,并且成员在他们可以绑定到调用站点上的变量时死亡(我错了吗?),并且类似结构的结构化绑定按预期工作.
是否可以将成员的生命延长/传递到外部变量,或者忽略移动/复制?我需要它与c ++ 14版本,但我无法让它在c ++ 17上工作,所以我对两者都感兴趣.
游乐场:
#include <tuple>
#include <iostream>
using std::cout;
class Shawty {
/**
* Pronounced shouty.
**/
public:
Shawty() : _id(Shawty::id++) {cout << _id << " ctor\n"; }
Shawty(Shawty && s) : _id(Shawty::id++) { cout << _id << " moved from " << s._id << "\n"; }
Shawty(const Shawty & s) …
Run Code Online (Sandbox Code Playgroud) 当我使用许多模板化的类并从它们派生时,我最近发现了"发明"这个简单的结构.我不确定这是不是常见的做法,还是我在脖子上系绳子.
template <typename T> class Base {};
template <typename T> class Derived : public Base<T>{
typedef Base<T> Base;
};
Run Code Online (Sandbox Code Playgroud)
我发现如果Base
类typedef
对某些类型有自己的s,它会特别有用.例如:
template <typename T> class Base {
typedef T Scalar;
typedef Matrix<Scalar> Matrix;
};
Run Code Online (Sandbox Code Playgroud)
然后很容易"导入"类型Derived
.它可以节省重新键入模板签名的费用.例如:
template <typename T> class Derived : public Base<T>{
typename Base<T>::Matrix yuck_yuck(); //that's what I am trying to simplify
typedef typename Base<T> Base;
typedef typename Base::Matrix Matrix;
Matrix much_fun(); //looks way better
};
Run Code Online (Sandbox Code Playgroud)
另外一个很大的优点是,当你想在Base
类中添加另一个模板参数时.您不必更改一堆功能,只需更新即可typedef
.much_fun
不会有任何问题,如果Base …
我无法理解为什么下面的代码没有将数据包放到线上(通过wireshark确认).POST
我认为,这是发送HTTP 请求的一种相当标准的方法.我不打算只阅读任何内容POST
.
private void sendRequest() throws IOException {
String params = "param=value";
URL url = new URL(otherUrl.toString());
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setDoInput(true); //setting this to `false` does not help
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "text/plain");
con.setRequestProperty("Content-Length", "" + Integer.toString(params.getBytes().length));
con.setRequestProperty("Accept", "text/plain");
con.setUseCaches(false);
con.connect();
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(params);
wr.flush();
wr.close();
//Logger.getLogger("log").info("URL: "+url+", response: "+con.getResponseCode());
con.disconnect();
}
Run Code Online (Sandbox Code Playgroud)
会发生什么......实际上什么都没有,除非我试着读什么.例如,通过取消注释读取响应代码的上述日志行.尝试通过读取响应con.getInputStream();
也有效.数据包没有移动.当我取消注释时getResponseCode
,我可以看到POST
发送了http ,然后200 OK
被发回.订单是正确的.即在发送POST之前我没有得到一些疯狂的回应.其他一切看起来完全一样(如果需要,我可以附上wireshark截图).在调试器中代码执行(即不阻塞任何地方).
我不明白在什么情况下会发生这种情况.我相信它应该是可能的,发送POST
请求con.setDoInput(false);
.目前它没有发送任何东西或失败(当试图执行时con.getResponseCode()
)有异常,因为我显然承诺我不会读任何东西.
可能相关的是,在sendRequest
我从同一网站请求一些数据之前,我相信我会正确地关闭所有数据.即: …