通过值传递字符串'当地价值的变化反映在原始价值中

时间:2016-10-04 09:17:37

标签: c++ string pass-by-value

为什么我的局部变量值的变化会反映到原始变量中?我在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;
}

3 个答案:

答案 0 :(得分:5)

一旦你写了

buff[2] = 'x';

并编译你的代码所有赌注都关闭了。 Per [string.accessors]

const charT* c_str() const noexcept;
     
      
  1. Returns:指针pp + i == &operator[](i)中的每个i [0,size()]
  2.   
  3. Complexity:恒定时间。
  4.   
  5. Requires: 程序不得更改存储在字符数组中的任何值。
  6.   

强调我的

由于您不允许修改指针所指向的字符,但您具有未定义的行为。此时编译器可以做任何想做的事情。试图找出它为什么做它所做的事情是没有意义的,因为任何其他编译器可能都不会这样做。

故事的寓意是不要把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