为什么我的局部变量值的变化会反映到原始变量中?我在C ++中通过值传递。
SELECT SKU, ORDER_MONTH,
SUM(PRICE) as Price
FROM (SELECT EXTRACT(YEAR FROM ORDERDATE) AS ORDER_YEAR,
SKU,
MONTHNAME(ORDERDATE) AS ORDER_MONTH,
ORDERDATE,
PRICE FROM ORDER_ABSTRACT )A
WHERE ORDER_YEAR=2016 AND SKU = 'AHMD1234'
GROUP BY SKU,MONTH(ORDERDATE)
#include <string>
#include <iostream>
void test(std::string a)
{
char *buff = (char *)a.c_str();
buff[2] = 'x';
std::cout << "In function: " << a;
}
int main()
{
std::string s = "Hello World";
std::cout << "Before : "<< s << "\n" ;
test(s);
std::cout << "\n" << "After : " << s << std::endl;
return 0;
}
答案 0 :(得分:5)
一旦你写了
buff[2] = 'x';
并编译你的代码所有赌注都关闭了。 Per [string.accessors]
const charT* c_str() const noexcept;
Returns:
指针p
,p + i == &operator[](i)
中的每个i
[0,size()]
。Complexity:
恒定时间。- 醇>
Requires:
程序不得更改存储在字符数组中的任何值。
强调我的
由于您不允许修改指针所指向的字符,但您具有未定义的行为。此时编译器可以做任何想做的事情。试图找出它为什么做它所做的事情是没有意义的,因为任何其他编译器可能都不会这样做。
故事的寓意是不要把const
抛弃,除非你确定你知道自己在做什么,如果你确实需要,然后记录代码以告诉你你在做什么
答案 1 :(得分:0)
您的std::string
实现仅使用operator[]
(或其他某种方法)修改字符串时才使用引用计数并进行深层复制。将const char*
返回值c_str()
转换为char*
会导致未定义的行为。
我相信,因为C ++ 11 std::string
不能再进行引用计数,所以切换到C ++ 11可能足以让你的代码工作(编辑:我没有实际检查之前,似乎我的假设是错误的)。
为了安全起见,请考虑寻找一个可以保证深度复制的字符串实现(或者自己实现一个)。
答案 2 :(得分:0)
#include <cstring>
#include <string>
#include <iostream>
void test(std::string a)
{
// modification trough valid std::string API
a[2] = 'x';
const char *buff = a.c_str(); // only const char* is available from API
std::cout << "In function: " << a << " | Trough pointer: " << buff;
// extraction to writeable char[] buffer
char writeableBuff[100];
// unsafe, possible attack trough buffer overflow, don't use in real code
strcpy(writeableBuff, a.c_str());
writeableBuff[3] = 'y';
std::cout << "\n" << "In writeable buffer: " << writeableBuff;
}
int main()
{
std::string s = "Hello World";
std::cout << "Before : "<< s << "\n" ;
test(s);
std::cout << "\n" << "After : " << s << std::endl;
return 0;
}
输出:
Before : Hello World
In function: Hexlo World | Trough pointer: Hexlo World
In writeable buffer: Hexyo World
After : Hello World